notebook-intelligence 4.8.0__tar.gz → 5.0.0__tar.gz

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.
Files changed (209) hide show
  1. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/.copier-answers.yml +2 -2
  2. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/.gitignore +10 -0
  3. notebook_intelligence-5.0.0/CHANGELOG.md +356 -0
  4. notebook_intelligence-5.0.0/CONTRIBUTING.md +202 -0
  5. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/PKG-INFO +81 -24
  6. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/README.md +69 -17
  7. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/SECURITY.md +1 -1
  8. notebook_intelligence-5.0.0/docs/admin-guide.md +726 -0
  9. notebook_intelligence-5.0.0/docs/admin-tour-config.md +180 -0
  10. notebook_intelligence-5.0.0/docs/skills.md +121 -0
  11. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/docs/troubleshooting.md +8 -2
  12. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/jest.config.js +5 -1
  13. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/__init__.py +1 -1
  14. notebook_intelligence-5.0.0/notebook_intelligence/_claude_cli.py +173 -0
  15. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/_version.py +1 -1
  16. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/ai_service_manager.py +28 -4
  17. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/base_chat_participant.py +1 -1
  18. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/built_in_toolsets.py +60 -50
  19. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/claude.py +268 -53
  20. notebook_intelligence-5.0.0/notebook_intelligence/claude_mcp_manager.py +350 -0
  21. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/claude_sessions.py +161 -103
  22. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/config.py +43 -7
  23. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/extension.py +1214 -68
  24. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/feature_flags.py +10 -0
  25. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/github_copilot.py +136 -6
  26. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/labextension/package.json +15 -8
  27. {notebook_intelligence-4.8.0/notebook_intelligence/labextension/schemas/@notebook-intelligence → notebook_intelligence-5.0.0/notebook_intelligence/labextension/schemas/@plmbr}/notebook-intelligence/package.json.orig +14 -7
  28. notebook_intelligence-5.0.0/notebook_intelligence/labextension/static/196.da0c2020639344d5c419.js +1 -0
  29. notebook_intelligence-5.0.0/notebook_intelligence/labextension/static/327.47473c656f6c27efa1dc.js +2 -0
  30. notebook_intelligence-5.0.0/notebook_intelligence/labextension/static/537.02c6edab4e3a352bb107.js +1 -0
  31. notebook_intelligence-5.0.0/notebook_intelligence/labextension/static/631.f00d05d8305a78ec8301.js +1 -0
  32. notebook_intelligence-5.0.0/notebook_intelligence/labextension/static/671.1b1a53f5f75bff82950b.js +1 -0
  33. notebook_intelligence-5.0.0/notebook_intelligence/labextension/static/694.2ebfa9714301d9260bf0.js +1 -0
  34. notebook_intelligence-5.0.0/notebook_intelligence/labextension/static/728.cae98e1655349e508971.js +1 -0
  35. notebook_intelligence-5.0.0/notebook_intelligence/labextension/static/745.f63673e66e02301096f4.js +2 -0
  36. notebook_intelligence-5.0.0/notebook_intelligence/labextension/static/784.e320c845743830167ef6.js +1 -0
  37. notebook_intelligence-5.0.0/notebook_intelligence/labextension/static/977.b917f705175326af0e5d.js +1 -0
  38. notebook_intelligence-5.0.0/notebook_intelligence/labextension/static/editor.worker.js +1407 -0
  39. notebook_intelligence-5.0.0/notebook_intelligence/labextension/static/remoteEntry.4708b983f8e8c8f2abe1.js +1 -0
  40. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/labextension/static/style.js +1 -1
  41. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/labextension/static/third-party-licenses.json +10 -10
  42. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/llm_providers/github_copilot_llm_provider.py +34 -10
  43. notebook_intelligence-5.0.0/notebook_intelligence/mcp_client.py +152 -0
  44. notebook_intelligence-5.0.0/notebook_intelligence/mcp_config_validation.py +218 -0
  45. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/mcp_manager.py +6 -3
  46. notebook_intelligence-5.0.0/notebook_intelligence/plugin_manager.py +595 -0
  47. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/skill_github_import.py +32 -29
  48. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/skill_manager.py +115 -2
  49. notebook_intelligence-5.0.0/notebook_intelligence/skill_manifest.py +342 -0
  50. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/skill_reconciler.py +93 -49
  51. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/skillset.py +24 -1
  52. notebook_intelligence-5.0.0/notebook_intelligence/tour_config.py +337 -0
  53. notebook_intelligence-5.0.0/notebook_intelligence/util.py +538 -0
  54. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/package.json +14 -7
  55. notebook_intelligence-5.0.0/pyproject.toml +139 -0
  56. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/conftest.py +34 -1
  57. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_ai_service_manager_integration.py +100 -2
  58. notebook_intelligence-5.0.0/tests/test_builtin_toolset_cwd_sandbox.py +202 -0
  59. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_cell_output_features_response.py +40 -0
  60. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_claude_client.py +98 -0
  61. notebook_intelligence-5.0.0/tests/test_claude_mcp_manager.py +790 -0
  62. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_claude_sessions.py +317 -12
  63. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_claude_sessions_handler.py +80 -11
  64. notebook_intelligence-5.0.0/tests/test_claude_system_prompt.py +118 -0
  65. notebook_intelligence-5.0.0/tests/test_claude_tool_humanizer.py +68 -0
  66. notebook_intelligence-5.0.0/tests/test_claude_tool_path_sandbox.py +319 -0
  67. notebook_intelligence-5.0.0/tests/test_coding_agent_launchers.py +129 -0
  68. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_config_atomic_save.py +35 -0
  69. notebook_intelligence-5.0.0/tests/test_config_integration.py +375 -0
  70. notebook_intelligence-5.0.0/tests/test_file_upload.py +301 -0
  71. notebook_intelligence-5.0.0/tests/test_github_copilot_llm_provider.py +166 -0
  72. notebook_intelligence-5.0.0/tests/test_github_copilot_user_data_mode.py +72 -0
  73. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_image_context.py +100 -0
  74. notebook_intelligence-5.0.0/tests/test_mcp_client_shim.py +302 -0
  75. notebook_intelligence-5.0.0/tests/test_mcp_config_validation.py +315 -0
  76. notebook_intelligence-5.0.0/tests/test_plugin_manager.py +1243 -0
  77. notebook_intelligence-5.0.0/tests/test_policy_gate.py +294 -0
  78. notebook_intelligence-5.0.0/tests/test_redact_process_secrets.py +207 -0
  79. notebook_intelligence-5.0.0/tests/test_response_emitter.py +83 -0
  80. notebook_intelligence-5.0.0/tests/test_safe_anchor_uri.py +132 -0
  81. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_skill_github_import.py +129 -20
  82. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_skill_manager.py +262 -0
  83. notebook_intelligence-5.0.0/tests/test_skill_manifest.py +502 -0
  84. notebook_intelligence-5.0.0/tests/test_skill_reconciler.py +775 -0
  85. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_skills_handlers.py +442 -0
  86. notebook_intelligence-5.0.0/tests/test_tour_config.py +584 -0
  87. notebook_intelligence-5.0.0/tests/test_websocket_handler_integration.py +775 -0
  88. notebook_intelligence-5.0.0/tests/test_ws_callback_handler_leak.py +126 -0
  89. notebook_intelligence-5.0.0/tests/test_ws_handler_auth.py +105 -0
  90. notebook_intelligence-5.0.0/tests/ts/__mocks__/jupyterlab-apputils.ts +12 -0
  91. notebook_intelligence-5.0.0/tests/ts/__mocks__/jupyterlab-filebrowser.ts +9 -0
  92. notebook_intelligence-5.0.0/tests/ts/ask-user-question.test.tsx +168 -0
  93. notebook_intelligence-5.0.0/tests/ts/chat-progress-feedback.test.ts +76 -0
  94. notebook_intelligence-5.0.0/tests/ts/checkbox.test.tsx +76 -0
  95. notebook_intelligence-5.0.0/tests/ts/choose-workspace-directory.test.ts +89 -0
  96. notebook_intelligence-5.0.0/tests/ts/claude-mcp-paste.test.ts +198 -0
  97. notebook_intelligence-5.0.0/tests/ts/coding-agent-launchers.test.ts +77 -0
  98. notebook_intelligence-5.0.0/tests/ts/launcher-picker.test.tsx +73 -0
  99. notebook_intelligence-5.0.0/tests/ts/open-file-refresh-watcher.test.ts +523 -0
  100. notebook_intelligence-5.0.0/tests/ts/plugins-panel.test.tsx +303 -0
  101. notebook_intelligence-5.0.0/tests/ts/setup.ts +23 -0
  102. notebook_intelligence-5.0.0/tests/ts/skill-wire-format.test.ts +84 -0
  103. notebook_intelligence-5.0.0/tests/ts/task-target-notebook.test.ts +99 -0
  104. notebook_intelligence-5.0.0/tests/ts/terminal-drag.test.ts +183 -0
  105. notebook_intelligence-5.0.0/tests/ts/tour-config.test.ts +193 -0
  106. notebook_intelligence-5.0.0/tests/ts/tour-events.test.ts +40 -0
  107. notebook_intelligence-5.0.0/tests/ts/tour-overlay.test.tsx +422 -0
  108. notebook_intelligence-5.0.0/tests/ts/tour-state.test.ts +55 -0
  109. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/ts/utils.test.ts +102 -0
  110. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tsconfig.json +1 -1
  111. notebook_intelligence-5.0.0/ui-tests/.eslintrc.js +12 -0
  112. notebook_intelligence-5.0.0/ui-tests/README.md +73 -0
  113. notebook_intelligence-5.0.0/ui-tests/jupyter_server_test_config.py +26 -0
  114. notebook_intelligence-5.0.0/ui-tests/package.json +17 -0
  115. notebook_intelligence-5.0.0/ui-tests/playwright.config.ts +55 -0
  116. notebook_intelligence-5.0.0/ui-tests/tests/cell-output.spec.ts +85 -0
  117. notebook_intelligence-5.0.0/ui-tests/tests/chat-sidebar.spec.ts +149 -0
  118. notebook_intelligence-5.0.0/ui-tests/tests/claude-mcp-patch.spec.ts +88 -0
  119. notebook_intelligence-5.0.0/ui-tests/tests/extension.spec.ts +36 -0
  120. notebook_intelligence-5.0.0/ui-tests/tests/helpers.ts +35 -0
  121. notebook_intelligence-5.0.0/ui-tests/tests/launcher.spec.ts +89 -0
  122. notebook_intelligence-5.0.0/ui-tests/tests/notebook-toolbar.spec.ts +123 -0
  123. notebook_intelligence-5.0.0/ui-tests/tsconfig.json +11 -0
  124. notebook_intelligence-5.0.0/ui-tests/yarn.lock +5540 -0
  125. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/yarn.lock +148 -77
  126. notebook_intelligence-4.8.0/CHANGELOG.md +0 -205
  127. notebook_intelligence-4.8.0/CONTRIBUTING.md +0 -135
  128. notebook_intelligence-4.8.0/docs/admin-guide.md +0 -508
  129. notebook_intelligence-4.8.0/docs/skills.md +0 -80
  130. notebook_intelligence-4.8.0/notebook_intelligence/labextension/static/196.db3f5562c0372c6e07f6.js +0 -1
  131. notebook_intelligence-4.8.0/notebook_intelligence/labextension/static/313.d3668bf2674eafcf4573.js +0 -1
  132. notebook_intelligence-4.8.0/notebook_intelligence/labextension/static/327.fe6b84491254fcaf64bf.js +0 -2
  133. notebook_intelligence-4.8.0/notebook_intelligence/labextension/static/631.a549782dde8c94a5612d.js +0 -1
  134. notebook_intelligence-4.8.0/notebook_intelligence/labextension/static/671.1797d409270b24758991.js +0 -1
  135. notebook_intelligence-4.8.0/notebook_intelligence/labextension/static/694.3bcf1107fa397004be17.js +0 -1
  136. notebook_intelligence-4.8.0/notebook_intelligence/labextension/static/728.c436df7c2664f4cf8e16.js +0 -1
  137. notebook_intelligence-4.8.0/notebook_intelligence/labextension/static/745.54aab870383fe1bf44c8.js +0 -2
  138. notebook_intelligence-4.8.0/notebook_intelligence/labextension/static/830.eecfb0cd62e605cbbd1e.js +0 -1
  139. notebook_intelligence-4.8.0/notebook_intelligence/labextension/static/977.7e3d66ffc344a0af7a4e.js +0 -1
  140. notebook_intelligence-4.8.0/notebook_intelligence/labextension/static/editor.worker.js +0 -1407
  141. notebook_intelligence-4.8.0/notebook_intelligence/labextension/static/remoteEntry.64319537c5af580d82c4.js +0 -1
  142. notebook_intelligence-4.8.0/notebook_intelligence/skill_manifest.py +0 -193
  143. notebook_intelligence-4.8.0/notebook_intelligence/util.py +0 -117
  144. notebook_intelligence-4.8.0/pyproject.toml +0 -90
  145. notebook_intelligence-4.8.0/tests/test_config_integration.py +0 -166
  146. notebook_intelligence-4.8.0/tests/test_file_upload.py +0 -143
  147. notebook_intelligence-4.8.0/tests/test_skill_manifest.py +0 -195
  148. notebook_intelligence-4.8.0/tests/test_skill_reconciler.py +0 -394
  149. notebook_intelligence-4.8.0/tests/test_websocket_handler_integration.py +0 -266
  150. notebook_intelligence-4.8.0/tests/ts/setup.ts +0 -13
  151. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/.prettierignore +0 -0
  152. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/.yarnrc.yml +0 -0
  153. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/LICENSE +0 -0
  154. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/PRIVACY.md +0 -0
  155. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/RELEASE.md +0 -0
  156. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/docs/rulesets.md +0 -0
  157. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/install.json +0 -0
  158. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/jupyter-config/server-config/notebook_intelligence.json +0 -0
  159. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/api.py +0 -0
  160. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/cell_output.py +0 -0
  161. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/context_factory.py +0 -0
  162. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/github_copilot_chat_participant.py +0 -0
  163. {notebook_intelligence-4.8.0/notebook_intelligence/labextension/schemas/@notebook-intelligence → notebook_intelligence-5.0.0/notebook_intelligence/labextension/schemas/@plmbr}/notebook-intelligence/plugin.json +0 -0
  164. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/labextension/static/1b55f12eca93ba6743e7.ttf +0 -0
  165. /notebook_intelligence-4.8.0/notebook_intelligence/labextension/static/327.fe6b84491254fcaf64bf.js.LICENSE.txt → /notebook_intelligence-5.0.0/notebook_intelligence/labextension/static/327.47473c656f6c27efa1dc.js.LICENSE.txt +0 -0
  166. /notebook_intelligence-4.8.0/notebook_intelligence/labextension/static/745.54aab870383fe1bf44c8.js.LICENSE.txt → /notebook_intelligence-5.0.0/notebook_intelligence/labextension/static/745.f63673e66e02301096f4.js.LICENSE.txt +0 -0
  167. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/labextension/static/be02dcbf2787b0b29ec8.module.wasm +0 -0
  168. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/labextension/static/e589c9ba04e3e5a90081.module.wasm +0 -0
  169. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/labextension/static/editor.worker.js.LICENSE.txt +0 -0
  170. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/llm_providers/litellm_compatible_llm_provider.py +0 -0
  171. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/llm_providers/ollama_llm_provider.py +0 -0
  172. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/llm_providers/openai_compatible_llm_provider.py +0 -0
  173. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/prompts.py +0 -0
  174. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/rule_injector.py +0 -0
  175. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/rule_manager.py +0 -0
  176. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/notebook_intelligence/ruleset.py +0 -0
  177. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/schema/plugin.json +0 -0
  178. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/setup.py +0 -0
  179. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/fixtures/rules/01-test-global.md +0 -0
  180. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/fixtures/rules/02-test-security.md +0 -0
  181. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/fixtures/rules/03-invalid-rule.md +0 -0
  182. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/fixtures/rules/modes/agent/01-test-production.md +0 -0
  183. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/fixtures/rules/modes/ask/01-test-exploration.md +0 -0
  184. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/fixtures/rules/modes/inline-chat/01-test-quick.md +0 -0
  185. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_api_hygiene.py +0 -0
  186. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_base_chat_participant_integration.py +0 -0
  187. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_cell_output.py +0 -0
  188. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_claude_models.py +0 -0
  189. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_context_factory.py +0 -0
  190. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_end_to_end_rule_integration.py +0 -0
  191. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_feature_flags.py +0 -0
  192. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_feedback.py +0 -0
  193. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_mcp_manager.py +0 -0
  194. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_models.py +0 -0
  195. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_openai_compatible_llm_provider.py +0 -0
  196. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_rule_auto_reload.py +0 -0
  197. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_rule_injector.py +0 -0
  198. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_rule_manager.py +0 -0
  199. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/test_skill_fetch_redirects.py +0 -0
  200. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/ts/__mocks__/svg.ts +0 -0
  201. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/ts/__mocks__/tiktoken.ts +0 -0
  202. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/ts/cell-output-bundle.test.ts +0 -0
  203. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/ts/cell-output-features.test.ts +0 -0
  204. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/ts/cell-output-toolbar.test.ts +0 -0
  205. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/ts/mcp-util.test.ts +0 -0
  206. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/ts/notebook-generation.test.ts +0 -0
  207. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/ts/tsconfig.json +0 -0
  208. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/tests/ts/workspace-skips.test.ts +0 -0
  209. {notebook_intelligence-4.8.0 → notebook_intelligence-5.0.0}/webpack.config.js +0 -0
@@ -6,9 +6,9 @@ author_name: Mehmet Bektas
6
6
  has_binder: false
7
7
  has_settings: true
8
8
  kind: server
9
- labextension_name: '@notebook-intelligence/notebook-intelligence'
9
+ labextension_name: '@plmbr/notebook-intelligence'
10
10
  project_short_description: Notebook Intelligence extension for JupyterLab
11
11
  python_name: notebook_intelligence
12
- repository: https://github.com/notebook-intelligence/notebook-intelligence
12
+ repository: https://github.com/plmbr/notebook-intelligence
13
13
  test: false
14
14
 
@@ -122,12 +122,22 @@ dmypy.json
122
122
 
123
123
  # End of https://www.gitignore.io/api/python
124
124
 
125
+ # Galata / Playwright UI tests
126
+ ui-tests/test-results/
127
+ ui-tests/playwright-report/
128
+ ui-tests/.cache/
129
+ ui-tests/.tsbuild/
130
+
125
131
  # OSX files
126
132
  .DS_Store
127
133
 
128
134
  # Yarn cache
129
135
  .yarn/
130
136
 
137
+ # Local AI assistant config and runtime state
138
+ .codex/
139
+ .claude/scheduled_tasks.lock
140
+
131
141
  # gh-pages
132
142
  _site/
133
143
  Gemfile.lock
@@ -0,0 +1,356 @@
1
+ # Changelog
2
+
3
+ All notable changes to Notebook Intelligence are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html) starting with 4.0.0.
6
+
7
+ For each release we list user-facing changes grouped as **Added**, **Changed**, **Fixed**, and **Removed**. Commits are squashed into the change that motivated them; the full git log remains the source of truth for low-level history.
8
+
9
+ <!-- <START NEW CHANGELOG ENTRY> -->
10
+
11
+ ## [Unreleased]
12
+
13
+ ## [5.0.0] - 2026-05-22
14
+
15
+ 5.0.0 is a major release built on top of 4.8.0, gathering a large surface of new admin policies, accessibility work across the chat sidebar / popovers / settings tabs, several security hardening passes, and three new agent-aware UI surfaces. Most existing configuration continues to work; the version bump reflects the breadth of new admin-policy / env-var surface that operators should review, plus the dependency swap from `fastmcp` to the official `mcp` SDK.
16
+
17
+ ### Migration note
18
+
19
+ 5.0.0 ships no traitlet, env-var, REST route, or NBI-owned on-disk format renames or removals. Four items operators should review before upgrading:
20
+
21
+ - **`fastmcp` is no longer a dependency** (#324). NBI now uses the official `mcp` SDK via a thin internal shim. If your image pinned `fastmcp` because prior docs recommended it, drop that pin. If you have downstream Python code that imported `fastmcp` transitively via NBI, declare `fastmcp` as a direct dependency in your own image.
22
+ - **Shell tool and Claude UI-bridge tool paths are now sandboxed to `jupyter_root`** (#290, #323). An agent-supplied absolute path or `..` traversal that previously resolved outside the workspace is now rejected. Workflows that relied on the agent reaching outside the workspace via these tools need to move that data into the workspace.
23
+ - **Session listing no longer reads `~/.claude/projects/<cwd>/history.jsonl`** (#310). No action required: the unified inventory walks `~/.claude/projects/` directly, and a stale or missing `history.jsonl` no longer hides resumable sessions.
24
+ - **Workspace file attach in Claude mode ships an `@`-mention pointer instead of inlined file content** (#327). Behavior change visible to end users (images, large files, and notebooks now work where they didn't); no admin action required, but Claude's Read tool counts toward tool-use quotas that the prior content-injection path did not.
25
+ - **Copilot WebSocket upgrades require Jupyter session authentication and pass an origin check** (#301). Cross-origin and unauthenticated upgrade attempts that previously succeeded against `WebsocketCopilotHandler` now return 403. If you have a custom client outside the JupyterLab page hitting this endpoint, it needs to pipe through Jupyter's auth (token or cookie) and either set its `Origin` to the lab's origin or have it added to `c.ServerApp.allow_origin`.
26
+
27
+ ### Added
28
+
29
+ #### Settings: three new top-level tabs and policy gates
30
+
31
+ - **Skills as a top-level Settings tab** (#224). Promoted from a Claude-mode sub-tab; visible in any mode, with a hint banner when Claude mode is off. New admin policy `skills_management_policy` (env `NBI_SKILLS_MANAGEMENT_POLICY`); `force-off` hides the tab, returns HTTP 403 from every `/notebook-intelligence/skills/*` route, and suppresses the managed-skills reconciler.
32
+ - **Claude MCP Servers tab** (#225) for managing the user, project, and local-scope MCP entries Claude Code reads from `~/.claude.json` and `<project>/.mcp.json`. Independent of the existing NBI MCP tab; the two never appear at the same time. New admin policy `claude_mcp_management_policy` (env `NBI_CLAUDE_MCP_MANAGEMENT_POLICY`).
33
+ - **Claude Plugins tab** (#226) wrapping `claude plugin` for install / uninstall / enable / disable / marketplace add. New admin policies `claude_plugins_management_policy` (env `NBI_CLAUDE_PLUGINS_MANAGEMENT_POLICY`) and `allow_github_plugin_import` (env `NBI_ALLOW_GITHUB_PLUGIN_IMPORT`), the latter mirroring `allow_github_skill_import` for marketplace sources.
34
+ - **Plugin marketplace picker** (#284). Browse the configured marketplaces and install plugins inline; the picker shows source repo, version, and description for each entry.
35
+ - **Plugin marketplace details + Update button** (#303). The Plugins tab now displays each installed plugin's description, author, version, and source, and surfaces a per-plugin **Update** button when a newer version is available upstream.
36
+ - **Per-workspace MCP server disable** for Claude mode (#286). Toggle individual MCP entries on/off without removing them, scoped to the current Jupyter workspace.
37
+ - **JSON-paste path in the Add MCP server dialog** (#285). Paste a Claude / Cursor / VS Code MCP config blob; NBI parses, validates, and pre-fills the form.
38
+ - **GitHub auth for plugin marketplace add**. Marketplace sources that resolve as GitHub URLs or `owner/repo` shorthand reuse Skills' `GITHUB_TOKEN` / `GH_TOKEN` / `gh auth token` precedence; tokens are injected into the `claude plugin marketplace add` subprocess via env, never argv.
39
+
40
+ #### Launchers
41
+
42
+ - **Launcher tiles for opencode, Pi, and GitHub Copilot CLI** (#268), with follow-ons for **OpenAI Codex** and brand icons for Codex and opencode (#333). Each tile appears when the corresponding binary is on `PATH` and opens a Jupyter terminal at the file-browser's current directory. CLI path overrides: `NBI_OPENCODE_CLI_PATH`, `NBI_PI_CLI_PATH`, `NBI_GITHUB_COPILOT_CLI_PATH`, `NBI_CODEX_CLI_PATH`. Capabilities response gains matching `*_cli_available` booleans.
43
+ - **Coding-agent launcher tiles can be hidden by admin policy** (#288). New traitlet `disabled_coding_agent_launchers` (list of `claude-code` / `opencode` / `pi` / `github-copilot-cli` / `codex`) with an optional `allow_enabling_coding_agent_launchers_with_env` + `NBI_ENABLED_CODING_AGENT_LAUNCHERS` per-pod re-enable mechanism. The Coding Agent section header now uses the sparkles icon instead of the Claude orange so the section is correctly framed when other tiles are enabled (#325).
44
+ - **Claude Code launcher tile is no longer gated by Claude chat mode** (#239); it appears whenever the `claude` CLI is on `PATH`.
45
+ - **Choose a start directory from the launcher tile** (#332). Clicking any coding-agent tile (or "New Session" on the Claude resume dialog) opens a directory picker so the terminal starts where the user wants.
46
+
47
+ #### Chat sidebar and agentic UX
48
+
49
+ - **Real progress feedback during long Claude tasks** (#254). Elapsed-time counter, heartbeat-driven pulse with a "may be slow" copy flip after 30 seconds, and inline tool-call narration.
50
+ - **"New chat session" button** in the chat sidebar header restarts the Claude SDK client, mirroring `/clear` (#246).
51
+ - **Terminal drag-drop file attach** with `@`-mention or shell-escaped raw modes and a per-terminal toolbar toggle (#256). New admin policy `NBI_TERMINAL_DRAG_DROP_POLICY`; tunables `NBI_UPLOAD_MAX_MB` (default `50`) and `NBI_UPLOAD_RETENTION_HOURS` (default `24`) govern the shared upload-staging endpoint used by both terminal drops and chat-sidebar attachments.
52
+ - **Workspace files attach as `@`-mention in Claude mode** (#327). Instead of reading file contents client-side and injecting them as a fenced code block, the backend emits an `@<workspace-relative-path>` pointer and Claude's Read tool decides what to load. Unblocks images, large files, and notebooks (cell-aware reads) that the content-injection path couldn't handle. Notebook cell-pointer prose and text-selection line ranges are preserved so deictic references ("explain this cell", "why is this broken") still have a referent.
53
+ - **Hover preview for image context thumbnails** (#267).
54
+ - **Reload open document tabs when their files change on disk** (#330, relocated in #339). Polls every open `DocumentWidget` and reverts via `context.revert()` when disk is newer than the in-memory model, skipping when the tab has unsaved local edits. New user setting `refresh_open_files_on_disk_change` (default `true`); flip in the **NBI Settings dialog → External changes**. Closes the agentic-experience gap where Claude edits a file but the open tab keeps showing the pre-edit version. Admins can pin via the matching `NBI_REFRESH_OPEN_FILES_ON_DISK_CHANGE_POLICY` env var or `refresh_open_files_on_disk_change_policy` traitlet.
55
+ - **First-run tour of the chat sidebar** (#304). Highlights the gear, file-attach button, chat-mode dropdown, and (when available) the Claude session history icon. Replays from the command palette via "Show NBI tour"; capability-aware so steps for unavailable CLIs are skipped.
56
+ - **Steered the Claude system prompt away from over-eager notebook creation** (#336). The agent now defaults to answering questions in chat instead of creating a new notebook to hold the answer when the user attaches a file and asks a question about it.
57
+
58
+ #### Copilot models
59
+
60
+ - **Dynamic GitHub Copilot model discovery** (#269). NBI queries `https://api.githubcopilot.com/models` on each Copilot token refresh and rebuilds the chat-model dropdown from the live response, falling back to a hardcoded list on transient failure.
61
+ - **Newer GitHub Copilot chat models** added to the fallback list (#255).
62
+
63
+ #### Skills and workspace config
64
+
65
+ - **Multi-manifest support** in `NBI_SKILLS_MANIFEST` / `skills_manifest` (#321). Comma-separated list of URLs and/or filesystem paths; manifests are unioned with first-wins URL dedupe and per-entry name-collision surfacing. See [`docs/skills.md`](docs/skills.md#managed-skills-via-an-org-manifest).
66
+ - **Tracks-upstream flag for user-imported GitHub skills** (#322). The Import-from-GitHub dialog adds a **Track upstream** checkbox; tracked skills get a per-skill Sync button and a panel-level **Sync tracking skills** button. Mutually exclusive with the managed-skills reconciler: a skill the reconciler installs can't also be marked tracking.
67
+ - **HTTP kill switch for the managed-skills reconciler** (#291). `POST /notebook-intelligence/skills/reconciler/stop` is authenticated, idempotent, and intentionally has no `/start` companion (a kill switch a script can flip back on isn't a kill switch). The reconciler also re-reads `NBI_SKILLS_MANAGEMENT_POLICY` at the start of each cycle and self-stops when it reads `force-off`.
68
+ - **Skill GitHub archive cap raised to 100 MB**, configurable (#257). New traitlet `skill_max_archive_mb` (env `NBI_SKILL_MAX_ARCHIVE_MB`); `0` disables the cap.
69
+ - **`additional_skipped_workspace_directories` accepted in NBI `config.json`** (#241), layered additively on top of the existing traitlet, env, and env-prefix layers so a per-user override extends rather than replaces the org-wide list.
70
+
71
+ ### Changed
72
+
73
+ #### Accessibility (chat sidebar, popovers, settings)
74
+
75
+ A multi-PR accessibility pass landed across most NBI surfaces. Together these make NBI navigable end-to-end with the keyboard and screen-reader, audited under JupyterLab's light, dark, and high-contrast themes:
76
+
77
+ - **Chat-sidebar header icons** are real keyboard-reachable buttons (#205, #305) with distinct titles / `aria-label`s and a button reset to avoid double-borders.
78
+ - **Settings tabs** are an ARIA tablist with arrow-key navigation (#206).
79
+ - **Workspace, tools, and slash popovers** are keyboard-first (#306), with focus restoration to the trigger element on close.
80
+ - **Settings checkboxes** have the WAI-ARIA `checkbox` role and respond to Space activation (#309).
81
+ - **Ask-User-Question form** uses `radio` for single-select choices, stable per-form `useId`-driven labels, and real form semantics (#307).
82
+ - **Claude MCP form** wires every input to a `<label>` (#308).
83
+ - **"Open notebook" link in chat replies** is a real button with the notebook path in its accessible name (#311).
84
+ - **Skills panel icons** render as real SVGs with focus-reveal styling; the nested-button wrapper is gone (#312).
85
+ - **Send button** swaps its color to the warn-token and updates its `aria-label` while a request is in flight (#313).
86
+ - **Inline-completion popover** uses JupyterLab theme tokens instead of a fixed pastel background so it reads correctly under dark/high-contrast themes (#314).
87
+ - **Upload-in-progress chip** announces via `role=status`, `aria-live=polite`, `aria-busy=true`, plus an animated ellipsis with `prefers-reduced-motion` honored (#315).
88
+ - **Drop-zone chip** uses theme-aware foreground color so the text is legible against the brand-tinted background (#316).
89
+ - **Generating-state rotating border** pauses under `prefers-reduced-motion` (#317).
90
+ - **Streaming chat replies** announce through an `aria-live=polite` region with chunked boundary announcements (#318).
91
+ - **Visually-hidden skip-to-message-input link** as the first focusable child of the sidebar (#319). Lets keyboard users jump past long transcripts to the prompt input.
92
+ - **Global Ctrl/Cmd+Shift+L shortcut** focuses the NBI chat input from anywhere in the app (#320).
93
+
94
+ - **Chat-input footer icons reworded** for clarity; the gear button gains a `title` attribute (#271).
95
+ - **Cell-tool descriptions** mention zero-based indexing so models pick the right cell (#265).
96
+
97
+ ### Removed
98
+
99
+ - **`fastmcp` dependency**, replaced with the official `mcp` SDK (#324). NBI's external behavior is unchanged; downstream code that imported `fastmcp` transitively via NBI now needs to depend on it directly.
100
+ - **`history.jsonl` as the gate for session listing** (#310). The unified inventory walks the projects directory directly.
101
+
102
+ ### Fixed
103
+
104
+ - **Websocket writes from worker threads** no longer raise `BufferError` after `/clear` or "new chat" on Python 3.13+ (#270). All emitter writes route through `tornado.IOLoop.call_soon_threadsafe`.
105
+ - **WebSocket message-callback handlers** are freed when requests finish, preventing slow accumulation over the lifetime of a session (#294).
106
+ - **Claude session listing** unified across the chat-sidebar picker and the launcher tile; both surfaces read the same on-disk transcript inventory and apply the same "show this session?" filter so they no longer disagree (#310). The legacy `history.jsonl` gate is removed.
107
+ - **Claude session preview** correctly strips the NBI context preamble when `claude.py` joined it onto the user's actual prompt (#331). Single-turn sessions previously showed a blank title; now they show the prompt.
108
+ - **Refresh-on-disk watcher** no longer throws `Invalid area: down` on every poll (post-#330 follow-up). The TS `Area` union lists `'down'`, but `LabShell.widgets()` doesn't implement it.
109
+ - **Cell tools** follow the active notebook when the user switches tabs (#253).
110
+ - **`is_connected()`** stabilized against the Claude worker-spawn resurrection race (#250).
111
+ - **Persisted Claude model** now displays after a JupyterLab restart (#244).
112
+ - **`/clear` no longer duplicated** in the `@`-mention autocomplete (#243).
113
+ - **`@`-mention picker** refreshes when workspace files change (#251) and closes on Escape from the search input (#266).
114
+ - **Notebook-toolbar prompt textarea** focuses when the popover opens (#240); the update button works outside Claude mode (#238).
115
+ - **Inline chat** anchors to the cursor line (#191).
116
+ - **Disabled send button** styled neutrally instead of as a primary action (#276); Claude tool-result check renders on the right of its label (#277).
117
+ - **Plugin Settings row** shows the plugin name even when the CLI returns only `id` (#280).
118
+
119
+ ### Security
120
+
121
+ - **Shell tool's `working_directory` is sandboxed to `jupyter_root`** (#290). A previously-permitted absolute path or `..` traversal in agent-supplied input is now rejected; the existing path-safety helper handles the canonicalization.
122
+ - **Claude UI-bridge tool paths sandboxed to `jupyter_root`** (#323). `open_file_in_jupyter_ui` and `run_command_in_jupyter_terminal` both route through `safe_jupyter_path` so an agent can't reach files outside the workspace via these tools. The Claude Agent SDK subprocess is itself rooted at `jupyter_root` via its `cwd` option.
123
+ - **Encrypted GitHub token file enforces mode 0o600** (#293). The file holding the AES-GCM-encrypted Copilot token is created and re-tightened to owner-only read/write on every save, so an out-of-band `chmod` that widens permissions is undone on the next write.
124
+ - **Process-env secrets are scrubbed from shell-tool output** (#295). The shell tool no longer leaks `API_KEY` / `TOKEN` / `SECRET`-like env values into the captured stdout/stderr block returned to the model.
125
+ - **MCP user config shape validated before persisting** (#299). Malformed entries in the JSON paste / Add-MCP dialog are rejected server-side (unknown keys, type/command/url consistency, etc.); the client surfaces the rejection as a notification rather than writing through.
126
+ - **Anchor URIs in chat messages filtered against an XSS allowlist** (#296). `javascript:`, `data:`, `vbscript:`, and tab/NEL/bidi-override codepoint smuggling are blocked at render time.
127
+ - **Copilot WebSocket upgrades authenticated and origin-checked** (#301). Cross-origin and unauthenticated upgrade attempts are refused.
128
+ - **GitHub Enterprise host detection for marketplace add** (#292), so a `git.acme.example.com` URL routes through the GHE token / API path instead of being misclassified as public GitHub. Hardened against trailing-dot, userinfo, and other URL-shape edge cases.
129
+ - **`fastmcp` dropped in favor of the official `mcp` Python SDK** (#324). `fastmcp` pinned `python-dotenv>=1.1.0` which conflicted with `litellm`'s `python-dotenv==1.0.1` pin; the swap unblocks installs on Python 3.14 and picks up CVE fixes via `urllib3>=2.7.0` (CVE-2026-44431 / CVE-2026-44432).
130
+ - **Runtime kill switch for the managed-skills reconciler** (#291) provides per-pod incident response without a server restart. See the Skills entry above for the user-facing affordances and the [admin guide](docs/admin-guide.md#disabling-the-skills-tab) for the route and self-stop semantics.
131
+
132
+ ### Internal
133
+
134
+ - **CVE-driven dependency upgrades** (#197); `react-icons` bumped to `~5.6.0` (#245).
135
+ - **Galata-based Playwright UI test suite scaffolded** (#207) and expanded with user-flow specs covering the chat sidebar, notebook toolbar, cell outputs, and the launcher (#272).
136
+ - **Docs refresh across README, admin guide, skills, and CHANGELOG** (#287) covering the post-4.8.0 surface that this release expands on.
137
+ - **Stop tracking local AI-assistant config files** (`.codex/`, `.claude/scheduled_tasks.lock`) via `.gitignore` so they don't clutter the diff when contributors run the agents inside the repo.
138
+ - **Contributor docs** cover the traitlet vs env var vs config-file decision (#242).
139
+
140
+ <!-- <END NEW CHANGELOG ENTRY> -->
141
+
142
+ ## [4.8.0] - 2026-05-11
143
+
144
+ ### Added
145
+
146
+ - **`allow_github_skill_import` traitlet** (env `NBI_ALLOW_GITHUB_SKILL_IMPORT`) gating user-initiated skill imports from GitHub independently of the managed-skills reconciler (#222). When `False`, the **Import from GitHub** button hides and `/skills/import` returns HTTP 403.
147
+ - **Workspace picker honors `.gitignore`** and gains the `additional_skipped_workspace_directories` traitlet (env `NBI_ADDITIONAL_SKIPPED_WORKSPACE_DIRECTORIES`, layered additively) for extending the built-in skip list (#223). Dot-prefixed files are also skipped by default (#221).
148
+ - Workspace file scan in the `@`-mention picker now runs in parallel (#227).
149
+
150
+ ### Changed
151
+
152
+ - Skill imports from GitHub block and scope HTTP redirects, including refusing HTTPS-to-HTTP downgrades (#203).
153
+ - Settings tab content scrolls correctly when its body is taller than the dialog (#228); the tab bar styling is standardized across tabs.
154
+
155
+ ### Fixed
156
+
157
+ - `NBIConfig.save()` is atomic (#202): symlinks are preserved, file mode is preserved across the swap, and the rename is parent-dir fsynced. Prevents the corrupt-config failure mode where a crash mid-write left an empty `config.json`.
158
+ - The NBI notebook toolbar is disabled outside Claude mode where its buttons did not work (#228); a stray new-notebook button was removed.
159
+
160
+ ## [4.7.0] — 2026-05-07
161
+
162
+ ### Added
163
+
164
+ - **Cell output actions** — right-click a cell output (or hover for the toolbar) for **Explain**, **Ask**, and **Troubleshoot** quick actions that open the chat sidebar with the output already attached as context. Outputs forward as structured MIME bundles and include images for vision-capable models, token-bounded so large outputs don't overflow the context window. Per-user toggles in `config.json` (`enable_explain_error`, `enable_output_followup`, `enable_output_toolbar`, default on); admins can lock them via `NBI_EXPLAIN_ERROR_POLICY` / `NBI_OUTPUT_FOLLOWUP_POLICY` / `NBI_OUTPUT_TOOLBAR_POLICY`.
165
+ - **Image attachments in chat** — paste or attach images alongside a prompt; the image goes to the model as input when it's vision-capable.
166
+ - **Streaming inline-chat responses** — the inline chat popover now streams tokens as they arrive instead of waiting for the full response.
167
+ - **Notebook toolbar generation button** — a sparkle icon on the active notebook's toolbar opens a popover that scopes the generation to that notebook.
168
+ - **Claude Code launcher tile** — a Claude Code tile in the JupyterLab launcher opens a session picker (resume a transcript or start a new one in the file browser's active subdirectory). Session IDs are copyable from the picker.
169
+ - **Repo-level `AGENTS.md`** — when a project root contains `AGENTS.md`, NBI appends it under the system prompt's "Additional Guidelines" alongside the existing ruleset injection.
170
+ - **Claude WebSocket heartbeat** — keeps long-running Claude agent requests alive through upstream proxy / load balancer idle timeouts (e.g. JupyterHub's nginx default of 60s) by sending a status heartbeat every 20s while a request is in flight. Fixes Bedrock-style request failures where processing exceeds the proxy idle window.
171
+ - **Extended admin policy coverage** — every Settings panel toggle is now lockable via an env var. New boolean policies: `NBI_CLAUDE_MODE_POLICY`, `NBI_CLAUDE_CONTINUE_CONVERSATION_POLICY`, `NBI_CLAUDE_CODE_TOOLS_POLICY`, `NBI_CLAUDE_JUPYTER_UI_TOOLS_POLICY`, `NBI_CLAUDE_SETTING_SOURCE_USER_POLICY`, `NBI_CLAUDE_SETTING_SOURCE_PROJECT_POLICY`, `NBI_STORE_GITHUB_ACCESS_TOKEN_POLICY`. New value-presence locks: `NBI_CHAT_MODEL_PROVIDER`, `NBI_CHAT_MODEL_ID`, `NBI_INLINE_COMPLETION_MODEL_PROVIDER`, `NBI_INLINE_COMPLETION_MODEL_ID`, `NBI_CLAUDE_CHAT_MODEL`, `NBI_CLAUDE_INLINE_COMPLETION_MODEL`, `ANTHROPIC_API_KEY`, `ANTHROPIC_BASE_URL`. See [README → Admin policies](README.md#admin-policies).
172
+ - `/claude-sessions` HTTP route accepts `?scope=cwd` to filter to sessions whose recorded `cwd` matches the lab's working directory.
173
+
174
+ ### Changed
175
+
176
+ - Claude agent connection now happens in the background so JupyterLab finishes loading without waiting on the SDK handshake.
177
+
178
+ ### Fixed
179
+
180
+ - Public-API hygiene in `notebook_intelligence.api`: `raise NotImplemented` → `raise NotImplementedError` (the former raised `TypeError` at the call site), `Toolset(tools=[])` and four other shared-default-argument cases corrected, `Signal.disconnect` tolerates double-disconnect with a debug-level log, registrar methods raise a new `RegistrationError` instead of silently logging.
181
+ - Claude headers (model + version) are now sent on inline completion calls, matching the chat path.
182
+ - OpenAI-compatible provider drops the unsupported `tool` `strict` flag when targeting vLLM (#108).
183
+ - Resolve symlinks when locating Claude session transcripts so `~/.claude/projects/` symlinked off another volume keeps working.
184
+ - Claude worker thread no longer crashes on cancellation; the chat loop recovers cleanly.
185
+ - "Generating..." row no longer reflows the chat sidebar on narrow widths.
186
+ - Skills popup in the chat sidebar dismisses on click-outside or when the input is cleared.
187
+ - Spurious "Skills reloaded" notification when launching a Claude session. The watcher now keys off a structural signature of bundle dirs + `SKILL.md` mtimes, ignoring sibling writes (`.DS_Store`, `.git/`, log/cache files) to the parent `~/.claude/skills/` directory.
188
+ - Traitlets `DeprecationWarning` ("Traits should be given as instances, not types") at startup is silenced for the `disabled_*` config.
189
+
190
+ ### Internal
191
+
192
+ - CI runs `pytest tests/` and `jlpm test` on every PR. The `[test]` extra was added to `pyproject.toml`. Both build jobs declare `permissions: { contents: read }` so a compromised step can't push.
193
+
194
+ <!-- <END NEW CHANGELOG ENTRY> -->
195
+
196
+ ## [4.6.0] — 2026-04-29
197
+
198
+ ### Added
199
+
200
+ - **Claude Skills management panel** — Settings now exposes a **Skills** tab for managing the bundles Claude can invoke (SKILL.md frontmatter, helper files, allowed tools). Skills resolve from `~/.claude/skills/` (user) and `<project>/.claude/skills/` (project) — the same locations the Claude CLI reads. Inline editor, duplicate / rename / delete with undo, and import-from-GitHub via the public tarball API. For organization deployments, NBI can install a curated set from a YAML manifest pointed at by `NBI_SKILLS_MANIFEST` and keep them in sync; managed skills are read-only in the UI. See [`docs/skills.md`](docs/skills.md) for the full reference.
201
+ - Restructured documentation: `README.md` rewritten with a TOC and concept glossary, plus new `SECURITY.md`, `PRIVACY.md`, and operator guides under `docs/` (`admin-guide.md`, `rulesets.md`, `skills.md`, `troubleshooting.md`).
202
+
203
+ ### Fixed
204
+
205
+ - **Windows Claude mode reliability** — Claude agent thread now uses the Proactor event loop on Windows, fixing subprocess spawn failures and intermittent "Claude agent not connected" races at startup. The Claude SDK retry path also reconnects when the worker thread has died instead of waiting out the full response timeout.
206
+ - Anthropic credentials are normalized (whitespace + scheme handling) before being passed to the SDK.
207
+ - Skill imports from GitHub reject tarball entries with absolute paths or `../` traversal — a malicious or buggy bundle can no longer write outside its install directory.
208
+ - `_send_claude_agent_request` guarded against the disconnect race that left chat handlers waiting on a closed queue.
209
+ - WebSocket message handlers are disconnected when the originating request finishes; previously they accumulated for the lifetime of the WebSocket.
210
+ - `configChanged` handlers are disconnected when components unmount, fixing a slow leak when the chat sidebar was opened and closed repeatedly.
211
+ - Claude session picker list scrolls correctly when the transcript count exceeds the visible area.
212
+
213
+ <!-- This entry was filled in retroactively after the 4.6.0 tag shipped. -->
214
+
215
+ ## [4.5.0] — 2026-04-09
216
+
217
+ ### Added
218
+
219
+ - Chat feedback mechanism for AI responses, configurable via the `enable_chat_feedback` traitlet, with a `telemetry` event hook.
220
+ - Attach files as context in chat.
221
+ - `Shift+Enter` inserts a newline in the chat input.
222
+ - Disable LLM providers via the `disabled_providers` traitlet, with optional per-pod re-enable via `NBI_ENABLED_PROVIDERS`.
223
+
224
+ ### Changed
225
+
226
+ - Inline completion for the OpenAI-compatible provider now uses the Chat Completions API.
227
+
228
+ ### Fixed
229
+
230
+ - OpenAI-compatible provider now correctly handles `tool` and `tool_choice` parameters.
231
+ - File-attach popover styling.
232
+ - Newlines in user input are preserved.
233
+
234
+ ## [4.4.0] — 2026-03-13
235
+
236
+ ### Added
237
+
238
+ - Configurable Claude Code CLI path via the `NBI_CLAUDE_CLI_PATH` environment variable.
239
+
240
+ ### Changed
241
+
242
+ - Subprocess invocations no longer use `shell=True`.
243
+
244
+ ## [4.3.2] — 2026-03-13
245
+
246
+ ### Fixed
247
+
248
+ - Refresh-models button in Claude settings; model list pulled from the Anthropic SDK.
249
+
250
+ ## [4.3.1] — 2026-01-12
251
+
252
+ ### Fixed
253
+
254
+ - Inline-chat autocomplete popover position.
255
+
256
+ ## [4.3.0] — 2026-01-11
257
+
258
+ ### Added
259
+
260
+ - Auto-complete debounce delay configuration.
261
+ - Additional inline-completion options in Claude mode.
262
+ - Conversation continuation in Claude mode.
263
+
264
+ ### Changed
265
+
266
+ - Settings dialog hides Claude-specific options when Claude mode is off.
267
+ - NBI sidebar moved to the left side of the JupyterLab UI.
268
+
269
+ ### Fixed
270
+
271
+ - Auto-complete tab-state handling.
272
+
273
+ ## [4.2.1] — 2026-01-06
274
+
275
+ ### Changed
276
+
277
+ - Project rebrand from "JUI" to "NBI" (`@notebook-intelligence/notebook-intelligence`).
278
+
279
+ ## [4.2.0] — 2026-01-06
280
+
281
+ ### Changed
282
+
283
+ - Notebook tool calls (e.g., cell execution) now require explicit user approval instead of being auto-allowed.
284
+
285
+ ### Fixed
286
+
287
+ - Improved error handling and message-handler disconnect.
288
+ - Claude settings font color and UI state when toggling Claude mode.
289
+
290
+ ## [4.1.2] — 2026-01-05
291
+
292
+ ### Fixed
293
+
294
+ - Lock-handling in long-running Claude sessions.
295
+
296
+ ## [4.1.1] — 2026-01-04
297
+
298
+ ### Fixed
299
+
300
+ - Claude mode reliability (multiple cleanup commits).
301
+
302
+ ## [4.1.0] — 2026-01-03
303
+
304
+ ### Added
305
+
306
+ - Plan mode for Claude.
307
+ - Custom message for the Bash tool.
308
+
309
+ ### Changed
310
+
311
+ - Claude session timeout raised to 30 minutes.
312
+ - Improved AskUserQuestion styling.
313
+
314
+ ### Fixed
315
+
316
+ - Current-directory context and chat-history handling.
317
+
318
+ ## [4.0.0] — 2026-01-01
319
+
320
+ ### Added
321
+
322
+ - **Claude mode** — first-class integration with [Claude Code](https://code.claude.com/), including:
323
+ - Claude Code-backed Agent Chat UI, inline chat, and auto-complete.
324
+ - Claude Code tools, skills, MCP servers, and custom commands available inside JupyterLab.
325
+ - Claude session resume from `~/.claude/projects/`.
326
+ - Honor `c.ServerApp.base_url` for all extension routes.
327
+
328
+ ### Changed
329
+
330
+ - Settings UI restructured around Claude vs default mode.
331
+ - WebSocket connection reliability improvements.
332
+
333
+ [unreleased]: https://github.com/plmbr/notebook-intelligence/compare/v5.0.0...HEAD
334
+ [5.0.0]: https://github.com/plmbr/notebook-intelligence/compare/v4.8.0...v5.0.0
335
+ [4.8.0]: https://github.com/plmbr/notebook-intelligence/compare/v4.7.0...v4.8.0
336
+ [4.7.0]: https://github.com/plmbr/notebook-intelligence/compare/v4.6.0...v4.7.0
337
+ [4.6.0]: https://github.com/plmbr/notebook-intelligence/compare/v4.5.0...v4.6.0
338
+ [4.5.0]: https://github.com/plmbr/notebook-intelligence/compare/v4.4.0...v4.5.0
339
+ [4.4.0]: https://github.com/plmbr/notebook-intelligence/compare/v4.3.2...v4.4.0
340
+ [4.3.2]: https://github.com/plmbr/notebook-intelligence/compare/v4.3.1...v4.3.2
341
+ [4.3.1]: https://github.com/plmbr/notebook-intelligence/compare/v4.3.0...v4.3.1
342
+ [4.3.0]: https://github.com/plmbr/notebook-intelligence/compare/v4.2.1...v4.3.0
343
+ [4.2.1]: https://github.com/plmbr/notebook-intelligence/compare/v4.2.0...v4.2.1
344
+ [4.2.0]: https://github.com/plmbr/notebook-intelligence/compare/v4.1.2...v4.2.0
345
+ [4.1.2]: https://github.com/plmbr/notebook-intelligence/compare/v4.1.1...v4.1.2
346
+ [4.1.1]: https://github.com/plmbr/notebook-intelligence/compare/v4.1.0...v4.1.1
347
+ [4.1.0]: https://github.com/plmbr/notebook-intelligence/compare/v4.0.0...v4.1.0
348
+ [4.0.0]: https://github.com/plmbr/notebook-intelligence/releases/tag/v4.0.0
349
+
350
+ ## Versioning policy
351
+
352
+ - **Major (X.0.0)** — backward-incompatible changes to traitlets, environment variables, REST routes, or on-disk file formats. Major releases are accompanied by a migration note in this file.
353
+ - **Minor (4.Y.0)** — new features and traitlets. Existing configuration continues to work.
354
+ - **Patch (4.5.Z)** — bug fixes only.
355
+
356
+ Deprecations land in a minor release with a warning at startup, and are removed no earlier than the next major release.
@@ -0,0 +1,202 @@
1
+ # Contributing
2
+
3
+ Thanks for considering a contribution to Notebook Intelligence!
4
+
5
+ > **Just want to use NBI?** You don't need to read this file. `pip install notebook-intelligence` and the [README](README.md) quick start are all you need.
6
+
7
+ ## Filing a good bug report
8
+
9
+ Include the following so we can reproduce the issue:
10
+
11
+ - **NBI version** — output of `pip show notebook-intelligence`.
12
+ - **JupyterLab version** — output of `jupyter --version`.
13
+ - **Python version and OS** — `python --version`; macOS, Linux, or Windows plus version.
14
+ - **Browser** — Chrome, Firefox, or Safari plus version, if the issue is in the chat sidebar or settings UI.
15
+ - **LLM provider** — GitHub Copilot, OpenAI-compatible, LiteLLM-compatible, Ollama, or Claude mode, plus the model name.
16
+ - **Claude mode** — on or off.
17
+ - **Reproduction steps** — minimum sequence of clicks and messages.
18
+ - **Logs** — relevant excerpts from the JupyterLab terminal (server-side errors), the browser DevTools console (frontend errors), and any redacted contents of `~/.jupyter/nbi/config.json` if the issue is configuration-related.
19
+
20
+ See [`docs/troubleshooting.md`](docs/troubleshooting.md) for common problems with copy-pasteable fixes — check there first.
21
+
22
+ ## Reporting a security issue
23
+
24
+ Do not open a public GitHub issue. See [SECURITY.md](SECURITY.md) for the private-disclosure address.
25
+
26
+ ## Architecture overview
27
+
28
+ NBI has two halves:
29
+
30
+ - **Server extension** — Python package `notebook_intelligence/`. Runs inside Jupyter Server. Key entry points:
31
+ - `notebook_intelligence/extension.py` — tornado handlers, traitlets, route registration, server lifecycle.
32
+ - `notebook_intelligence/ai_service_manager.py` — composes LLM providers, MCP, skills, and rules into the request pipeline.
33
+ - `notebook_intelligence/llm_providers/` — provider adapters (GitHub Copilot, OpenAI-compatible, LiteLLM-compatible, Ollama).
34
+ - `notebook_intelligence/claude.py` + `notebook_intelligence/claude_sessions.py` — Claude Code integration via [`claude-agent-sdk`](https://pypi.org/project/claude-agent-sdk/).
35
+ - `notebook_intelligence/mcp_manager.py` — MCP server management via [`fastmcp`](https://pypi.org/project/fastmcp/).
36
+ - `notebook_intelligence/skill_manager.py`, `skill_github_import.py`, `skill_manifest.py`, `skill_reconciler.py`, `skillset.py` — Claude Skills storage, GitHub import, and managed-manifest reconciliation.
37
+ - `notebook_intelligence/rule_manager.py`, `rule_injector.py`, `ruleset.py` — ruleset discovery and prompt injection.
38
+ - `notebook_intelligence/built_in_toolsets.py` — built-in tool implementations (`nbi-notebook-edit`, `nbi-command-execute`, etc.).
39
+ - `notebook_intelligence/github_copilot.py` — GitHub Copilot device-flow auth and token storage.
40
+ - **Frontend extension** — TypeScript package `src/`. Compiled to a JupyterLab labextension. Key entry points:
41
+ - `src/index.ts` — JupyterLab plugin registration.
42
+ - `src/chat-sidebar.tsx` — chat sidebar React tree.
43
+ - `src/components/settings-panel.tsx` — settings dialog.
44
+ - `src/components/skills-panel.tsx` — Claude Skills management UI.
45
+ - `src/api.ts` — high-level client for the server extension (chat WebSocket, capabilities, config).
46
+ - `src/handler.ts` — thin wrapper over Jupyter's `ServerConnection.makeRequest`.
47
+
48
+ The two halves communicate over the routes registered in `extension.py` (REST and WebSocket). All routes live under `/notebook-intelligence/`. See [`docs/admin-guide.md`](docs/admin-guide.md#http-api-surface) for the full list.
49
+
50
+ ## Configuration mechanisms
51
+
52
+ NBI has three places a setting can be configured: a Python traitlet, an `NBI_*` environment variable, and an NBI config file (the Settings dialog is a friendly editor for the user-scope copy of the config file). They look similar but they exist for different audiences, and they override each other in a specific order.
53
+
54
+ Before adding a new knob at all, ask whether you actually need one. Hardcoded defaults are the simplest thing that works, and settings nobody ever changes shouldn't be settings — most candidates fail this gate.
55
+
56
+ ### Who decides the value?
57
+
58
+ There are three audiences, and the audience picks the mechanism.
59
+
60
+ **The end user, via the Settings dialog.** They change their own preference and want it to stick across restarts without touching files. Examples: `default_chat_mode`, `store_github_access_token`.
61
+
62
+ → Add a getter on `NBIConfig` (which reads `~/.jupyter/nbi/config.json`), surface the value in `/capabilities`, and add a control in `src/components/settings-panel.tsx`. Writes persist immediately.
63
+
64
+ **A server admin who runs `jupyter lab` directly.** They set an org-wide baseline in `jupyter_server_config.py` — typical for local installs and dev images. Examples: `disabled_providers`, `*_management_policy`.
65
+
66
+ → Declare a traitlet on `NotebookIntelligence` in `extension.py`. The `help=` text shows up in `jupyter` CLI output and in generated config templates.
67
+
68
+ **A deployment admin running JupyterHub / KubeSpawner.** They need the same setting to vary by pod without rebuilding the container image. Editing Python at spawn time is awkward; env vars are how Kubernetes-style deployments wire per-pod policy. Examples: `NBI_ALLOW_GITHUB_SKILL_IMPORT`, `NBI_*_POLICY`.
69
+
70
+ → Pair the traitlet with an `NBI_*` env var resolved at server startup. Use one of the fail-loud helpers in `extension.py`: `_resolve_bool_with_env`, `_resolve_policy_with_env`, or `_resolve_csv_appended`. A typo in the env var must surface at server startup, not silently fall through to the default — that's how deployment-admin debugging spirals into half-day investigations.
71
+
72
+ #### Rule: admin-policy flags must ship with an env var pair
73
+
74
+ If the setting is an admin-policy flag, the env var pairing isn't optional. A flag counts as an admin-policy flag when all three are true:
75
+
76
+ - Small shape: boolean, policy enum (e.g. `force-on` / `force-off` / `user-choice`), or short string-list.
77
+ - An admin (not the user) decides the value.
78
+ - The intent is to enforce, allow, or block a behavior.
79
+
80
+ `allow_github_skill_import` and every `*_management_policy` qualify. Numeric tuning knobs (`skills_manifest_interval`, `inline_completion_debouncer_delay`) don't — they aren't enforcement. Nested configs (`mcp_server_settings`, `claude_settings`) don't either — they're too big for a single env var and live in user `config.json` anyway.
81
+
82
+ The rule exists because every prior PR that shipped a policy traitlet without an env var pair got a follow-up adding the env var: deployment admins always need per-pod variance for policy flags. Doing the pair once is cheaper than doing it twice.
83
+
84
+ ### How values override each other
85
+
86
+ When more than one source supplies the same value, NBI resolves them in this order (top wins):
87
+
88
+ ```
89
+ 1. NBI_* environment variable
90
+ 2. user ~/.jupyter/nbi/config.json
91
+ 3. env-prefix <env>/share/jupyter/nbi/config.json
92
+ 4. traitlet in jupyter_server_config.py
93
+ 5. hardcoded default
94
+ ```
95
+
96
+ The mental model: items 2–5 are a chain of _defaults_, each more specific than the last (a default for everyone → installs → users → "what this user picked"). The env var is different — it's not a default, it's _policy enforcement_. A deployment admin sets an env var when they want to force a value regardless of what the user chose. That's why it sits on top of the user's own preference.
97
+
98
+ Worked example: a user unchecks "Store GitHub access token" in the Settings dialog. The toggle persists to user `config.json` and the value sticks across restarts — until an admin sets `NBI_STORE_GITHUB_ACCESS_TOKEN_POLICY=force-on` on the pod. After the next server restart, the user's `config.json` still says "off" but the value NBI uses is "on" — the env var wins.
99
+
100
+ That's the trap to know about: **if you expose a Settings-dialog control for a value that also has an admin override path, the user can see their save "stick" in the UI in-session and watch it silently revert on restart.** Two ways to avoid it:
101
+
102
+ 1. **Don't put it in the dialog at all.** If admins are supposed to enforce the value, the user shouldn't be able to toggle it via the UI. Manual `config.json` editing is fine for niche admin-overridable knobs (issue #232 is an example).
103
+ 2. **Use the policy triad and `settingLocks`.** For admin-enforceable settings, follow `*_management_policy`: the admin picks `force-on`, `force-off`, or `user-choice`. When the admin forces a value, the frontend's `settingLocks` shows a lock icon and disables the control — the user can see their choice is overridden rather than fighting an invisible policy.
104
+
105
+ ### When override-semantics are wrong: the additivity carve-out
106
+
107
+ Most settings overwrite each other (one layer wins). A small number of settings _append_ across layers instead — each layer can add to the resolved value but none can remove from it. `additional_skipped_workspace_directories` (#232) is the only example today: traitlet + env var + env-prefix config + user config all merge into one combined list, deduped.
108
+
109
+ If you add a new additive setting, document the polarity explicitly in both the traitlet `help=` and the admin-guide entry. Readers assume override-semantics by default; additivity has to be called out or it's a trap.
110
+
111
+ ### Adding a new admin policy is currently tedious
112
+
113
+ For historical reasons, every new admin policy has to be wired in seven places: the frontend type union (`src/api.ts`), the capabilities response builder (`extension.py`), the policy resolver, the handler class attribute, the README admin policies table, the admin-guide entry, and at least one pinning test. Miss one and the knob breaks in one direction without any error (e.g. the backend enforces but the UI doesn't lock the control, or vice versa).
114
+
115
+ The comment above `FEATURE_POLICY_SPEC` in `extension.py` lists every site — that's the closest thing to a guardrail today. A future registration helper that derived most of these from a single declaration would be a welcome cleanup.
116
+
117
+ ## Development install
118
+
119
+ You'll need Node.js 18 or newer to build the frontend. The `jlpm` command is JupyterLab's pinned version of [yarn](https://yarnpkg.com/) — install JupyterLab first to get it.
120
+
121
+ ```bash
122
+ # Clone the repo and change into the directory.
123
+ # Install the package in development mode.
124
+ pip install -e "."
125
+
126
+ # Link the development version of the extension with JupyterLab.
127
+ jupyter labextension develop . --overwrite
128
+
129
+ # Server extension must be manually installed in develop mode.
130
+ jupyter server extension enable notebook_intelligence
131
+
132
+ # Build the TypeScript source.
133
+ jlpm build
134
+ ```
135
+
136
+ Run JupyterLab and the watch loop in two terminals to pick up source changes automatically:
137
+
138
+ ```bash
139
+ # Terminal 1
140
+ jlpm watch
141
+ # Terminal 2
142
+ jupyter lab
143
+ ```
144
+
145
+ Refresh the browser tab to load the rebuilt frontend. To get source maps for JupyterLab core extensions as well:
146
+
147
+ ```bash
148
+ jupyter lab build --minimize=False
149
+ ```
150
+
151
+ ### Development uninstall
152
+
153
+ ```bash
154
+ jupyter server extension disable notebook_intelligence
155
+ pip uninstall notebook_intelligence
156
+ ```
157
+
158
+ The `jupyter labextension develop` command leaves a symlink behind. Run `jupyter labextension list` to find the labextensions directory, then remove the `@plmbr/notebook-intelligence` symlink there.
159
+
160
+ ## Running tests
161
+
162
+ TypeScript unit tests:
163
+
164
+ ```bash
165
+ jlpm test
166
+ ```
167
+
168
+ There is no Python test suite at the moment. Manual end-to-end verification is documented per change in pull request descriptions.
169
+
170
+ ## Linting
171
+
172
+ ```bash
173
+ jlpm lint:check # check, no fixes
174
+ jlpm lint # check and auto-fix prettier, eslint, and stylelint
175
+ ```
176
+
177
+ CI runs `lint:check`. Identifiers prefixed with `_` are treated as intentionally unused and excluded from the unused-vars rule.
178
+
179
+ If `jlpm install` produces unexpected lockfile changes, your local Yarn version probably differs from the one bundled with JupyterLab. `jlpm` ships with JupyterLab — use it directly instead of a system-wide `yarn`.
180
+
181
+ ## Packaging
182
+
183
+ See [RELEASE.md](RELEASE.md).
184
+
185
+ ## Frontend extension layout sanity check
186
+
187
+ If you see the frontend extension but it isn't working, check the server extension is enabled:
188
+
189
+ ```bash
190
+ jupyter server extension list
191
+ ```
192
+
193
+ If the server extension is enabled but the frontend isn't loading:
194
+
195
+ ```bash
196
+ jupyter labextension list
197
+ ```
198
+
199
+ ## Resources
200
+
201
+ - [Copilot Internals blog post](https://thakkarparth007.github.io/copilot-explorer/posts/copilot-internals.html)
202
+ - [B00TK1D/copilot-api](https://github.com/B00TK1D/copilot-api) — GitHub Copilot auth and inline completions