jupyterlab_claude_code_extension 1.2.12 → 1.2.19
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 +1 -0
- package/lib/icons.js +9 -0
- package/lib/widget.d.ts +1 -0
- package/lib/widget.js +25 -14
- package/package.json +1 -1
- package/src/__tests__/jupyterlab_claude_code_extension.spec.ts +20 -4
- package/src/icons.ts +11 -0
- package/src/widget.ts +27 -13
- package/style/base.css +8 -2
package/lib/icons.d.ts
CHANGED
package/lib/icons.js
CHANGED
|
@@ -67,6 +67,15 @@ export const branchIcon = new LabIcon({
|
|
|
67
67
|
name: 'jupyterlab_claude_code_extension:branch',
|
|
68
68
|
svgstr: branchSvgStr
|
|
69
69
|
});
|
|
70
|
+
// Arrow-switch glyph (Octicons arrow-switch-16, MIT) - marks the
|
|
71
|
+
// "Switch and Manage Sessions" submenu.
|
|
72
|
+
const switchSvgStr = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16">
|
|
73
|
+
<path class="jp-icon3" fill="#616161" d="M5.22 14.78a.75.75 0 0 0 1.06-1.06L4.56 12h8.69a.75.75 0 0 0 0-1.5H4.56l1.72-1.72a.75.75 0 0 0-1.06-1.06l-3 3a.75.75 0 0 0 0 1.06l3 3Zm5.56-6.5a.75.75 0 1 1-1.06-1.06l1.72-1.72H2.75a.75.75 0 0 1 0-1.5h8.69L9.72 2.28a.75.75 0 0 1 1.06-1.06l3 3a.75.75 0 0 1 0 1.06l-3 3Z"/>
|
|
74
|
+
</svg>`;
|
|
75
|
+
export const switchIcon = new LabIcon({
|
|
76
|
+
name: 'jupyterlab_claude_code_extension:switch',
|
|
77
|
+
svgstr: switchSvgStr
|
|
78
|
+
});
|
|
70
79
|
// Funnel copied verbatim from @jupyterlab/ui-components'
|
|
71
80
|
// `search/filter.svg` - the same image the file browser's filter
|
|
72
81
|
// toggle uses. The `class="jp-icon3"` lets JupyterLab's theme drive
|
package/lib/widget.d.ts
CHANGED
|
@@ -149,6 +149,7 @@ export declare class ClaudeCodeSessionsWidget extends Widget {
|
|
|
149
149
|
private _commands;
|
|
150
150
|
private _contextMenu;
|
|
151
151
|
private _branchSubmenu;
|
|
152
|
+
private _branchSessionMenu;
|
|
152
153
|
private _lastBranches;
|
|
153
154
|
private _lastBranchesCurrent;
|
|
154
155
|
private _newSessionMenu;
|
package/lib/widget.js
CHANGED
|
@@ -5,7 +5,7 @@ import { CommandRegistry } from '@lumino/commands';
|
|
|
5
5
|
import { UUID } from '@lumino/coreutils';
|
|
6
6
|
import { Menu, Widget } from '@lumino/widgets';
|
|
7
7
|
import { requestAPI } from './request';
|
|
8
|
-
import { addIcon, branchIcon, claudeIcon, filterIcon, refreshIcon, removeIcon, shieldIcon, starFilledIcon } from './icons';
|
|
8
|
+
import { addIcon, branchIcon, switchIcon, claudeIcon, filterIcon, refreshIcon, removeIcon, shieldIcon, starFilledIcon } from './icons';
|
|
9
9
|
const POLL_INTERVAL_MS = 30000;
|
|
10
10
|
const DEFAULT_RECENT_LIMIT = 10;
|
|
11
11
|
const EXPANDED_STORAGE_KEY = 'jupyterlab_claude_code_extension:expanded';
|
|
@@ -845,12 +845,14 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
845
845
|
starFilledIcon.element({ container: star });
|
|
846
846
|
row.appendChild(star);
|
|
847
847
|
}
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
848
|
+
// Always present (empty without an mtime) so the star column keeps
|
|
849
|
+
// the same anchor across every row in the panel.
|
|
850
|
+
const time = document.createElement('span');
|
|
851
|
+
time.className = 'jp-ClaudeSessionsPanel-rowTime';
|
|
852
|
+
time.textContent = session.file_mtime
|
|
853
|
+
? this._formatRelativeTime(session.file_mtime)
|
|
854
|
+
: '';
|
|
855
|
+
row.appendChild(time);
|
|
854
856
|
row.addEventListener('click', () => {
|
|
855
857
|
if (removing) {
|
|
856
858
|
return;
|
|
@@ -1073,12 +1075,11 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
1073
1075
|
}
|
|
1074
1076
|
});
|
|
1075
1077
|
this._commands.addCommand('claude-code-sessions:branch-session', {
|
|
1076
|
-
label: '
|
|
1077
|
-
icon: branchIcon,
|
|
1078
|
+
label: 'Normal',
|
|
1078
1079
|
execute: () => void this._branchSession(false)
|
|
1079
1080
|
});
|
|
1080
1081
|
this._commands.addCommand('claude-code-sessions:branch-session-dangerous', {
|
|
1081
|
-
label: '
|
|
1082
|
+
label: 'Skip Permissions',
|
|
1082
1083
|
icon: shieldIcon,
|
|
1083
1084
|
execute: () => void this._branchSession(true)
|
|
1084
1085
|
});
|
|
@@ -1116,6 +1117,18 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
1116
1117
|
this._branchSubmenu = new Menu({ commands: this._commands });
|
|
1117
1118
|
this._branchSubmenu.addClass('jp-ClaudeSessionsContextMenu');
|
|
1118
1119
|
this._branchSubmenu.title.label = 'Switch and Manage Sessions';
|
|
1120
|
+
this._branchSubmenu.title.icon = switchIcon;
|
|
1121
|
+
// Submenu grouping the two branch-session launch modes.
|
|
1122
|
+
this._branchSessionMenu = new Menu({ commands: this._commands });
|
|
1123
|
+
this._branchSessionMenu.addClass('jp-ClaudeSessionsContextMenu');
|
|
1124
|
+
this._branchSessionMenu.title.label = 'Branch Session';
|
|
1125
|
+
this._branchSessionMenu.title.icon = branchIcon;
|
|
1126
|
+
this._branchSessionMenu.addItem({
|
|
1127
|
+
command: 'claude-code-sessions:branch-session'
|
|
1128
|
+
});
|
|
1129
|
+
this._branchSessionMenu.addItem({
|
|
1130
|
+
command: 'claude-code-sessions:branch-session-dangerous'
|
|
1131
|
+
});
|
|
1119
1132
|
this._contextMenu = new Menu({ commands: this._commands });
|
|
1120
1133
|
this._contextMenu.addClass('jp-ClaudeSessionsContextMenu');
|
|
1121
1134
|
this._rebuildContextMenu(false);
|
|
@@ -1154,10 +1167,8 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
1154
1167
|
});
|
|
1155
1168
|
}
|
|
1156
1169
|
this._contextMenu.addItem({
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
this._contextMenu.addItem({
|
|
1160
|
-
command: 'claude-code-sessions:branch-session-dangerous'
|
|
1170
|
+
type: 'submenu',
|
|
1171
|
+
submenu: this._branchSessionMenu
|
|
1161
1172
|
});
|
|
1162
1173
|
this._contextMenu.addItem({
|
|
1163
1174
|
command: 'claude-code-sessions:cleanup-parallel'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jupyterlab_claude_code_extension",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.19",
|
|
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",
|
|
@@ -318,12 +318,22 @@ describe('launch spinner dismiss contract', () => {
|
|
|
318
318
|
const rowTime = (css.match(
|
|
319
319
|
/\.jp-ClaudeSessionsPanel-rowTime \{[\s\S]*?\}/
|
|
320
320
|
) ?? [''])[0];
|
|
321
|
-
expect(rowTime).toMatch(/width:
|
|
321
|
+
expect(rowTime).toMatch(/width: 4em/);
|
|
322
|
+
expect(rowTime).toMatch(/white-space: nowrap/);
|
|
322
323
|
expect(rowTime).toMatch(/text-align: right/);
|
|
323
324
|
const branchTime = (css.match(
|
|
324
325
|
/\.jp-ClaudeSessionsPanel-branchTime \{[\s\S]*?\}/
|
|
325
326
|
) ?? [''])[0];
|
|
326
|
-
expect(branchTime).toMatch(/width:
|
|
327
|
+
expect(branchTime).toMatch(/width: 4em/);
|
|
328
|
+
expect(branchTime).toMatch(/white-space: nowrap/);
|
|
329
|
+
// Stars line up vertically across the entire panel: every row keeps
|
|
330
|
+
// the time slot (empty without an mtime) and every section reserves
|
|
331
|
+
// the scrollbar gutter.
|
|
332
|
+
expect(widgetSrc).toMatch(/time\.textContent = session\.file_mtime\s*\?/);
|
|
333
|
+
const list = (css.match(/\.jp-ClaudeSessionsPanel-list \{[\s\S]*?\}/) ?? [
|
|
334
|
+
''
|
|
335
|
+
])[0];
|
|
336
|
+
expect(list).toMatch(/scrollbar-gutter: stable/);
|
|
327
337
|
expect(branchTime).toMatch(/text-align: right/);
|
|
328
338
|
});
|
|
329
339
|
|
|
@@ -337,14 +347,20 @@ describe('launch spinner dismiss contract', () => {
|
|
|
337
347
|
);
|
|
338
348
|
});
|
|
339
349
|
|
|
340
|
-
it('branch session
|
|
350
|
+
it('branch session is a submenu with normal and skip-permissions entries', () => {
|
|
341
351
|
expect(widgetSrc).toMatch(/claude-code-sessions:branch-session'/);
|
|
342
352
|
expect(widgetSrc).toMatch(
|
|
343
353
|
/claude-code-sessions:branch-session-dangerous/
|
|
344
354
|
);
|
|
345
355
|
expect(widgetSrc).toMatch(
|
|
346
|
-
/Branch Session
|
|
356
|
+
/_branchSessionMenu\.title\.label = 'Branch Session'/
|
|
357
|
+
);
|
|
358
|
+
expect(widgetSrc).toMatch(
|
|
359
|
+
/label: 'Skip Permissions',\s*icon: shieldIcon/
|
|
347
360
|
);
|
|
361
|
+
expect(widgetSrc).toMatch(/submenu: this\._branchSessionMenu/);
|
|
362
|
+
// No ellipsis on the branch-session labels.
|
|
363
|
+
expect(widgetSrc).not.toMatch(/Branch Session\.\.\./);
|
|
348
364
|
});
|
|
349
365
|
|
|
350
366
|
it('branch session asks for a name and launches a known fork id', () => {
|
package/src/icons.ts
CHANGED
|
@@ -82,6 +82,17 @@ export const branchIcon = new LabIcon({
|
|
|
82
82
|
svgstr: branchSvgStr
|
|
83
83
|
});
|
|
84
84
|
|
|
85
|
+
// Arrow-switch glyph (Octicons arrow-switch-16, MIT) - marks the
|
|
86
|
+
// "Switch and Manage Sessions" submenu.
|
|
87
|
+
const switchSvgStr = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16">
|
|
88
|
+
<path class="jp-icon3" fill="#616161" d="M5.22 14.78a.75.75 0 0 0 1.06-1.06L4.56 12h8.69a.75.75 0 0 0 0-1.5H4.56l1.72-1.72a.75.75 0 0 0-1.06-1.06l-3 3a.75.75 0 0 0 0 1.06l3 3Zm5.56-6.5a.75.75 0 1 1-1.06-1.06l1.72-1.72H2.75a.75.75 0 0 1 0-1.5h8.69L9.72 2.28a.75.75 0 0 1 1.06-1.06l3 3a.75.75 0 0 1 0 1.06l-3 3Z"/>
|
|
89
|
+
</svg>`;
|
|
90
|
+
|
|
91
|
+
export const switchIcon = new LabIcon({
|
|
92
|
+
name: 'jupyterlab_claude_code_extension:switch',
|
|
93
|
+
svgstr: switchSvgStr
|
|
94
|
+
});
|
|
95
|
+
|
|
85
96
|
// Funnel copied verbatim from @jupyterlab/ui-components'
|
|
86
97
|
// `search/filter.svg` - the same image the file browser's filter
|
|
87
98
|
// toggle uses. The `class="jp-icon3"` lets JupyterLab's theme drive
|
package/src/widget.ts
CHANGED
|
@@ -19,6 +19,7 @@ import { requestAPI } from './request';
|
|
|
19
19
|
import {
|
|
20
20
|
addIcon,
|
|
21
21
|
branchIcon,
|
|
22
|
+
switchIcon,
|
|
22
23
|
claudeIcon,
|
|
23
24
|
filterIcon,
|
|
24
25
|
refreshIcon,
|
|
@@ -996,12 +997,14 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
996
997
|
row.appendChild(star);
|
|
997
998
|
}
|
|
998
999
|
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1000
|
+
// Always present (empty without an mtime) so the star column keeps
|
|
1001
|
+
// the same anchor across every row in the panel.
|
|
1002
|
+
const time = document.createElement('span');
|
|
1003
|
+
time.className = 'jp-ClaudeSessionsPanel-rowTime';
|
|
1004
|
+
time.textContent = session.file_mtime
|
|
1005
|
+
? this._formatRelativeTime(session.file_mtime)
|
|
1006
|
+
: '';
|
|
1007
|
+
row.appendChild(time);
|
|
1005
1008
|
|
|
1006
1009
|
row.addEventListener('click', () => {
|
|
1007
1010
|
if (removing) {
|
|
@@ -1252,13 +1255,12 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
1252
1255
|
});
|
|
1253
1256
|
|
|
1254
1257
|
this._commands.addCommand('claude-code-sessions:branch-session', {
|
|
1255
|
-
label: '
|
|
1256
|
-
icon: branchIcon,
|
|
1258
|
+
label: 'Normal',
|
|
1257
1259
|
execute: () => void this._branchSession(false)
|
|
1258
1260
|
});
|
|
1259
1261
|
|
|
1260
1262
|
this._commands.addCommand('claude-code-sessions:branch-session-dangerous', {
|
|
1261
|
-
label: '
|
|
1263
|
+
label: 'Skip Permissions',
|
|
1262
1264
|
icon: shieldIcon,
|
|
1263
1265
|
execute: () => void this._branchSession(true)
|
|
1264
1266
|
});
|
|
@@ -1301,6 +1303,19 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
1301
1303
|
this._branchSubmenu = new Menu({ commands: this._commands });
|
|
1302
1304
|
this._branchSubmenu.addClass('jp-ClaudeSessionsContextMenu');
|
|
1303
1305
|
this._branchSubmenu.title.label = 'Switch and Manage Sessions';
|
|
1306
|
+
this._branchSubmenu.title.icon = switchIcon;
|
|
1307
|
+
|
|
1308
|
+
// Submenu grouping the two branch-session launch modes.
|
|
1309
|
+
this._branchSessionMenu = new Menu({ commands: this._commands });
|
|
1310
|
+
this._branchSessionMenu.addClass('jp-ClaudeSessionsContextMenu');
|
|
1311
|
+
this._branchSessionMenu.title.label = 'Branch Session';
|
|
1312
|
+
this._branchSessionMenu.title.icon = branchIcon;
|
|
1313
|
+
this._branchSessionMenu.addItem({
|
|
1314
|
+
command: 'claude-code-sessions:branch-session'
|
|
1315
|
+
});
|
|
1316
|
+
this._branchSessionMenu.addItem({
|
|
1317
|
+
command: 'claude-code-sessions:branch-session-dangerous'
|
|
1318
|
+
});
|
|
1304
1319
|
|
|
1305
1320
|
this._contextMenu = new Menu({ commands: this._commands });
|
|
1306
1321
|
this._contextMenu.addClass('jp-ClaudeSessionsContextMenu');
|
|
@@ -1342,10 +1357,8 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
1342
1357
|
});
|
|
1343
1358
|
}
|
|
1344
1359
|
this._contextMenu.addItem({
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
this._contextMenu.addItem({
|
|
1348
|
-
command: 'claude-code-sessions:branch-session-dangerous'
|
|
1360
|
+
type: 'submenu',
|
|
1361
|
+
submenu: this._branchSessionMenu
|
|
1349
1362
|
});
|
|
1350
1363
|
this._contextMenu.addItem({
|
|
1351
1364
|
command: 'claude-code-sessions:cleanup-parallel'
|
|
@@ -1803,6 +1816,7 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
1803
1816
|
private _commands!: CommandRegistry;
|
|
1804
1817
|
private _contextMenu!: Menu;
|
|
1805
1818
|
private _branchSubmenu!: Menu;
|
|
1819
|
+
private _branchSessionMenu!: Menu;
|
|
1806
1820
|
private _lastBranches: IBranch[] = [];
|
|
1807
1821
|
private _lastBranchesCurrent = '';
|
|
1808
1822
|
private _newSessionMenu!: Menu;
|
package/style/base.css
CHANGED
|
@@ -155,6 +155,10 @@
|
|
|
155
155
|
flex: 1 1 auto;
|
|
156
156
|
overflow-y: auto;
|
|
157
157
|
min-height: 0;
|
|
158
|
+
|
|
159
|
+
/* Reserve the scrollbar gutter in every section so star/time columns
|
|
160
|
+
line up across the entire panel, scrollbar or not. */
|
|
161
|
+
scrollbar-gutter: stable;
|
|
158
162
|
}
|
|
159
163
|
|
|
160
164
|
.jp-ClaudeSessionsPanel-row {
|
|
@@ -382,7 +386,8 @@
|
|
|
382
386
|
|
|
383
387
|
.jp-ClaudeSessionsPanel-branchTime {
|
|
384
388
|
flex: none;
|
|
385
|
-
width:
|
|
389
|
+
width: 4em;
|
|
390
|
+
white-space: nowrap;
|
|
386
391
|
text-align: right;
|
|
387
392
|
color: var(--jp-ui-font-color2);
|
|
388
393
|
font-size: var(--jp-ui-font-size0);
|
|
@@ -458,7 +463,8 @@
|
|
|
458
463
|
column so values line up across rows; the star column sits before it. */
|
|
459
464
|
.jp-ClaudeSessionsPanel-rowTime {
|
|
460
465
|
flex: 0 0 auto;
|
|
461
|
-
width:
|
|
466
|
+
width: 4em;
|
|
467
|
+
white-space: nowrap;
|
|
462
468
|
text-align: right;
|
|
463
469
|
color: var(--jp-ui-font-color2);
|
|
464
470
|
font-size: var(--jp-ui-font-size0);
|