jupyterlab_claude_code_extension 1.1.27 → 1.1.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/icons.d.ts CHANGED
@@ -5,5 +5,4 @@ export declare const refreshIcon: LabIcon;
5
5
  export declare const removeIcon: LabIcon;
6
6
  export declare const shieldIcon: LabIcon;
7
7
  export declare const addIcon: LabIcon;
8
- export declare const addShieldIcon: LabIcon;
9
8
  export declare const filterIcon: LabIcon;
package/lib/icons.js CHANGED
@@ -58,19 +58,6 @@ export const addIcon = new LabIcon({
58
58
  name: 'jupyterlab_claude_code_extension:add',
59
59
  svgstr: addSvgStr
60
60
  });
61
- // Plus with a small solid shield in the lower-right corner - the
62
- // skip-permissions variant of the "new session" button, echoing the
63
- // shield used on the context menu's "Resume (Skip Permissions)".
64
- const addShieldSvgStr = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16">
65
- <g class="jp-icon3" fill="#616161">
66
- <path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" transform="translate(-2,-2) scale(0.83)"/>
67
- <path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4z" transform="translate(13,12) scale(0.46)"/>
68
- </g>
69
- </svg>`;
70
- export const addShieldIcon = new LabIcon({
71
- name: 'jupyterlab_claude_code_extension:add-shield',
72
- svgstr: addShieldSvgStr
73
- });
74
61
  // Funnel copied verbatim from @jupyterlab/ui-components'
75
62
  // `search/filter.svg` - the same image the file browser's filter
76
63
  // toggle uses. The `class="jp-icon3"` lets JupyterLab's theme drive
package/lib/widget.d.ts CHANGED
@@ -107,6 +107,7 @@ export declare class ClaudeCodeSessionsWidget extends Widget {
107
107
  private _expanded;
108
108
  private _commands;
109
109
  private _contextMenu;
110
+ private _newSessionMenu;
110
111
  private _activeSession;
111
112
  private _activeRowEl;
112
113
  private _pollHandle;
package/lib/widget.js CHANGED
@@ -3,7 +3,7 @@ import { folderIcon, terminalIcon } from '@jupyterlab/ui-components';
3
3
  import { CommandRegistry } from '@lumino/commands';
4
4
  import { Menu, Widget } from '@lumino/widgets';
5
5
  import { requestAPI } from './request';
6
- import { addIcon, addShieldIcon, claudeIcon, filterIcon, refreshIcon, removeIcon, shieldIcon, starFilledIcon } from './icons';
6
+ import { addIcon, claudeIcon, filterIcon, refreshIcon, removeIcon, shieldIcon, starFilledIcon } from './icons';
7
7
  const POLL_INTERVAL_MS = 30000;
8
8
  const DEFAULT_RECENT_LIMIT = 10;
9
9
  const EXPANDED_STORAGE_KEY = 'jupyterlab_claude_code_extension:expanded';
@@ -144,15 +144,12 @@ export class ClaudeCodeSessionsWidget extends Widget {
144
144
  newBtn.className = 'jp-ClaudeSessionsPanel-iconButton';
145
145
  newBtn.title = 'New Claude session in the current folder';
146
146
  addIcon.element({ container: newBtn });
147
- newBtn.addEventListener('click', () => void this._newSession(false));
147
+ newBtn.addEventListener('click', () => {
148
+ // Drop the menu just below the button, left-aligned with it.
149
+ const rect = newBtn.getBoundingClientRect();
150
+ this._newSessionMenu.open(rect.left, rect.bottom);
151
+ });
148
152
  header.appendChild(newBtn);
149
- const newSkipBtn = document.createElement('button');
150
- newSkipBtn.className = 'jp-ClaudeSessionsPanel-iconButton';
151
- newSkipBtn.title =
152
- 'New Claude session in the current folder (Skip Permissions)';
153
- addShieldIcon.element({ container: newSkipBtn });
154
- newSkipBtn.addEventListener('click', () => void this._newSession(true));
155
- header.appendChild(newSkipBtn);
156
153
  const filterBtn = document.createElement('button');
157
154
  filterBtn.className = 'jp-ClaudeSessionsPanel-iconButton';
158
155
  filterBtn.title = 'Filter sessions';
@@ -1024,6 +1021,25 @@ export class ClaudeCodeSessionsWidget extends Widget {
1024
1021
  }
1025
1022
  }
1026
1023
  });
1024
+ this._commands.addCommand('claude-code-sessions:new-session', {
1025
+ label: 'New Claude Session',
1026
+ execute: () => void this._newSession(false)
1027
+ });
1028
+ this._commands.addCommand('claude-code-sessions:new-session-dangerous', {
1029
+ label: 'New Claude Session (Skip Permissions)',
1030
+ icon: shieldIcon,
1031
+ execute: () => void this._newSession(true)
1032
+ });
1033
+ // Dropdown for the header's plus button - same command registry and
1034
+ // styling as the row context menu.
1035
+ this._newSessionMenu = new Menu({ commands: this._commands });
1036
+ this._newSessionMenu.addClass('jp-ClaudeSessionsContextMenu');
1037
+ this._newSessionMenu.addItem({
1038
+ command: 'claude-code-sessions:new-session'
1039
+ });
1040
+ this._newSessionMenu.addItem({
1041
+ command: 'claude-code-sessions:new-session-dangerous'
1042
+ });
1027
1043
  this._contextMenu = new Menu({ commands: this._commands });
1028
1044
  this._contextMenu.addClass('jp-ClaudeSessionsContextMenu');
1029
1045
  this._contextMenu.addItem({ command: 'claude-code-sessions:resume' });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jupyterlab_claude_code_extension",
3
- "version": "1.1.27",
3
+ "version": "1.1.29",
4
4
  "description": "Browse, resume, and manage your Claude Code CLI sessions from a JupyterLab side panel. One click reactivates the right terminal - no duplicate tabs, live remote-control indicator, and favourites for the projects you keep coming back to.",
5
5
  "keywords": [
6
6
  "jupyter",
package/src/icons.ts CHANGED
@@ -71,21 +71,6 @@ export const addIcon = new LabIcon({
71
71
  svgstr: addSvgStr
72
72
  });
73
73
 
74
- // Plus with a small solid shield in the lower-right corner - the
75
- // skip-permissions variant of the "new session" button, echoing the
76
- // shield used on the context menu's "Resume (Skip Permissions)".
77
- const addShieldSvgStr = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16">
78
- <g class="jp-icon3" fill="#616161">
79
- <path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" transform="translate(-2,-2) scale(0.83)"/>
80
- <path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4z" transform="translate(13,12) scale(0.46)"/>
81
- </g>
82
- </svg>`;
83
-
84
- export const addShieldIcon = new LabIcon({
85
- name: 'jupyterlab_claude_code_extension:add-shield',
86
- svgstr: addShieldSvgStr
87
- });
88
-
89
74
  // Funnel copied verbatim from @jupyterlab/ui-components'
90
75
  // `search/filter.svg` - the same image the file browser's filter
91
76
  // toggle uses. The `class="jp-icon3"` lets JupyterLab's theme drive
package/src/widget.ts CHANGED
@@ -16,7 +16,6 @@ import { Message } from '@lumino/messaging';
16
16
  import { requestAPI } from './request';
17
17
  import {
18
18
  addIcon,
19
- addShieldIcon,
20
19
  claudeIcon,
21
20
  filterIcon,
22
21
  refreshIcon,
@@ -194,17 +193,13 @@ export class ClaudeCodeSessionsWidget extends Widget {
194
193
  newBtn.className = 'jp-ClaudeSessionsPanel-iconButton';
195
194
  newBtn.title = 'New Claude session in the current folder';
196
195
  addIcon.element({ container: newBtn });
197
- newBtn.addEventListener('click', () => void this._newSession(false));
196
+ newBtn.addEventListener('click', () => {
197
+ // Drop the menu just below the button, left-aligned with it.
198
+ const rect = newBtn.getBoundingClientRect();
199
+ this._newSessionMenu.open(rect.left, rect.bottom);
200
+ });
198
201
  header.appendChild(newBtn);
199
202
 
200
- const newSkipBtn = document.createElement('button');
201
- newSkipBtn.className = 'jp-ClaudeSessionsPanel-iconButton';
202
- newSkipBtn.title =
203
- 'New Claude session in the current folder (Skip Permissions)';
204
- addShieldIcon.element({ container: newSkipBtn });
205
- newSkipBtn.addEventListener('click', () => void this._newSession(true));
206
- header.appendChild(newSkipBtn);
207
-
208
203
  const filterBtn = document.createElement('button');
209
204
  filterBtn.className = 'jp-ClaudeSessionsPanel-iconButton';
210
205
  filterBtn.title = 'Filter sessions';
@@ -1195,6 +1190,28 @@ export class ClaudeCodeSessionsWidget extends Widget {
1195
1190
  }
1196
1191
  });
1197
1192
 
1193
+ this._commands.addCommand('claude-code-sessions:new-session', {
1194
+ label: 'New Claude Session',
1195
+ execute: () => void this._newSession(false)
1196
+ });
1197
+
1198
+ this._commands.addCommand('claude-code-sessions:new-session-dangerous', {
1199
+ label: 'New Claude Session (Skip Permissions)',
1200
+ icon: shieldIcon,
1201
+ execute: () => void this._newSession(true)
1202
+ });
1203
+
1204
+ // Dropdown for the header's plus button - same command registry and
1205
+ // styling as the row context menu.
1206
+ this._newSessionMenu = new Menu({ commands: this._commands });
1207
+ this._newSessionMenu.addClass('jp-ClaudeSessionsContextMenu');
1208
+ this._newSessionMenu.addItem({
1209
+ command: 'claude-code-sessions:new-session'
1210
+ });
1211
+ this._newSessionMenu.addItem({
1212
+ command: 'claude-code-sessions:new-session-dangerous'
1213
+ });
1214
+
1198
1215
  this._contextMenu = new Menu({ commands: this._commands });
1199
1216
  this._contextMenu.addClass('jp-ClaudeSessionsContextMenu');
1200
1217
  this._contextMenu.addItem({ command: 'claude-code-sessions:resume' });
@@ -1258,6 +1275,7 @@ export class ClaudeCodeSessionsWidget extends Widget {
1258
1275
  private _expanded: Record<SectionKey, boolean> = loadExpanded();
1259
1276
  private _commands!: CommandRegistry;
1260
1277
  private _contextMenu!: Menu;
1278
+ private _newSessionMenu!: Menu;
1261
1279
  private _activeSession: ISession | null = null;
1262
1280
  private _activeRowEl: HTMLElement | null = null;
1263
1281
  private _pollHandle: number | null = null;