jupyterlab_claude_code_extension 1.0.29 → 1.0.34
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/index.js +4 -3
- package/lib/widget.d.ts +6 -4
- package/lib/widget.js +22 -12
- package/package.json +1 -1
- package/src/index.ts +5 -4
- package/src/widget.ts +25 -12
package/lib/index.js
CHANGED
|
@@ -31,9 +31,10 @@ const plugin = {
|
|
|
31
31
|
try {
|
|
32
32
|
const settings = await settingRegistry.load(PLUGIN_ID);
|
|
33
33
|
const apply = () => {
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
const mode = settings.get('presentationMode').composite;
|
|
35
|
+
if (mode === 'session' || mode === 'folder' || mode === 'path') {
|
|
36
|
+
widget.setPresentationMode(mode);
|
|
37
|
+
}
|
|
37
38
|
const limit = settings.get('recentLimit').composite;
|
|
38
39
|
if (typeof limit === 'number') {
|
|
39
40
|
widget.setRecentLimit(limit);
|
package/lib/widget.d.ts
CHANGED
|
@@ -2,11 +2,12 @@ import { JupyterFrontEnd } from '@jupyterlab/application';
|
|
|
2
2
|
import { ITerminalTracker } from '@jupyterlab/terminal';
|
|
3
3
|
import { Widget } from '@lumino/widgets';
|
|
4
4
|
import { Message } from '@lumino/messaging';
|
|
5
|
+
export type PresentationMode = 'session' | 'folder' | 'path';
|
|
5
6
|
export declare class ClaudeCodeSessionsWidget extends Widget {
|
|
6
7
|
constructor(app: JupyterFrontEnd, rootDir: string, terminalTracker?: ITerminalTracker | null);
|
|
7
8
|
refresh(): void;
|
|
8
|
-
/**
|
|
9
|
-
|
|
9
|
+
/** Choose how rows are labelled: by session name, folder name, or path. */
|
|
10
|
+
setPresentationMode(mode: PresentationMode): void;
|
|
10
11
|
/** Set how many rows the Recent section displays. */
|
|
11
12
|
setRecentLimit(n: number): void;
|
|
12
13
|
/** Toggle the --dangerously-skip-permissions flag on launched sessions. */
|
|
@@ -40,7 +41,8 @@ export declare class ClaudeCodeSessionsWidget extends Widget {
|
|
|
40
41
|
private _findTerminalForCwd;
|
|
41
42
|
private _showCloseExistingDialog;
|
|
42
43
|
private _wireTerminalDisposal;
|
|
43
|
-
/** Apply the
|
|
44
|
+
/** Apply the presentation-mode setting (path-segment disambiguation is
|
|
45
|
+
* handled separately in ``_disambiguate``). */
|
|
44
46
|
private _displayName;
|
|
45
47
|
private _basename;
|
|
46
48
|
/** Walk path tails until every name in a colliding group is unique. */
|
|
@@ -74,7 +76,7 @@ export declare class ClaudeCodeSessionsWidget extends Widget {
|
|
|
74
76
|
private readonly _terminalsByPath;
|
|
75
77
|
private readonly _pendingByPath;
|
|
76
78
|
private readonly _rootDir;
|
|
77
|
-
private
|
|
79
|
+
private _presentationMode;
|
|
78
80
|
private _recentLimit;
|
|
79
81
|
private _dangerouslySkip;
|
|
80
82
|
private _displayNames;
|
package/lib/widget.js
CHANGED
|
@@ -6,6 +6,7 @@ import { claudeIcon, refreshIcon, removeIcon, shieldIcon, starFilledIcon } from
|
|
|
6
6
|
const POLL_INTERVAL_MS = 10000;
|
|
7
7
|
const DEFAULT_RECENT_LIMIT = 10;
|
|
8
8
|
const EXPANDED_STORAGE_KEY = 'jupyterlab_claude_code_extension:expanded';
|
|
9
|
+
const DEFAULT_PRESENTATION_MODE = 'session';
|
|
9
10
|
const SECTION_LABELS = {
|
|
10
11
|
favourites: 'Favourites',
|
|
11
12
|
recent: 'Recent',
|
|
@@ -65,7 +66,7 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
65
66
|
this._removingPaths = new Set();
|
|
66
67
|
this._terminalsByPath = new Map();
|
|
67
68
|
this._pendingByPath = new Map();
|
|
68
|
-
this.
|
|
69
|
+
this._presentationMode = DEFAULT_PRESENTATION_MODE;
|
|
69
70
|
this._recentLimit = DEFAULT_RECENT_LIMIT;
|
|
70
71
|
this._dangerouslySkip = false;
|
|
71
72
|
this._displayNames = new Map();
|
|
@@ -88,12 +89,12 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
88
89
|
.catch(err => this._showError(err))
|
|
89
90
|
.finally(() => this._setRefreshSpinning(false));
|
|
90
91
|
}
|
|
91
|
-
/**
|
|
92
|
-
|
|
93
|
-
if (this.
|
|
92
|
+
/** Choose how rows are labelled: by session name, folder name, or path. */
|
|
93
|
+
setPresentationMode(mode) {
|
|
94
|
+
if (this._presentationMode === mode) {
|
|
94
95
|
return;
|
|
95
96
|
}
|
|
96
|
-
this.
|
|
97
|
+
this._presentationMode = mode;
|
|
97
98
|
this._render();
|
|
98
99
|
}
|
|
99
100
|
/** Set how many rows the Recent section displays. */
|
|
@@ -417,12 +418,19 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
417
418
|
});
|
|
418
419
|
}
|
|
419
420
|
// -------------------------------------------------------------- rendering
|
|
420
|
-
/** Apply the
|
|
421
|
+
/** Apply the presentation-mode setting (path-segment disambiguation is
|
|
422
|
+
* handled separately in ``_disambiguate``). */
|
|
421
423
|
_displayName(s) {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
+
const folder = this._basename(s.project_path) || s.encoded_path;
|
|
425
|
+
switch (this._presentationMode) {
|
|
426
|
+
case 'folder':
|
|
427
|
+
return folder;
|
|
428
|
+
case 'path':
|
|
429
|
+
return this._displayPath(s.project_path) || folder;
|
|
430
|
+
case 'session':
|
|
431
|
+
default:
|
|
432
|
+
return s.name || folder;
|
|
424
433
|
}
|
|
425
|
-
return s.name || this._basename(s.project_path) || s.encoded_path;
|
|
426
434
|
}
|
|
427
435
|
_basename(p) {
|
|
428
436
|
if (!p) {
|
|
@@ -546,14 +554,14 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
546
554
|
}
|
|
547
555
|
else {
|
|
548
556
|
for (const item of items) {
|
|
549
|
-
list.appendChild(this._renderRow(item));
|
|
557
|
+
list.appendChild(this._renderRow(item, key));
|
|
550
558
|
}
|
|
551
559
|
}
|
|
552
560
|
section.appendChild(list);
|
|
553
561
|
}
|
|
554
562
|
this._bodyEl.appendChild(section);
|
|
555
563
|
}
|
|
556
|
-
_renderRow(session) {
|
|
564
|
+
_renderRow(session, sectionKey) {
|
|
557
565
|
const row = document.createElement('div');
|
|
558
566
|
row.className = 'jp-ClaudeSessionsPanel-row';
|
|
559
567
|
row.title = this._buildRowTooltip(session);
|
|
@@ -582,7 +590,9 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
582
590
|
name.className = 'jp-ClaudeSessionsPanel-name';
|
|
583
591
|
name.textContent = this._lookupName(session);
|
|
584
592
|
row.appendChild(name);
|
|
585
|
-
|
|
593
|
+
// No star in the Favourites section - every row there is a favourite
|
|
594
|
+
// by definition; stars are an indicator only useful in Recent/All.
|
|
595
|
+
if (session.favourite && sectionKey !== 'favourites') {
|
|
586
596
|
const star = document.createElement('span');
|
|
587
597
|
star.className = 'jp-ClaudeSessionsPanel-favStar';
|
|
588
598
|
star.title = 'Favourite';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jupyterlab_claude_code_extension",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.34",
|
|
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/index.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { ITerminalTracker } from '@jupyterlab/terminal';
|
|
|
9
9
|
|
|
10
10
|
import { requestAPI } from './request';
|
|
11
11
|
import { IStatusResponse } from './types';
|
|
12
|
-
import { ClaudeCodeSessionsWidget } from './widget';
|
|
12
|
+
import { ClaudeCodeSessionsWidget, PresentationMode } from './widget';
|
|
13
13
|
|
|
14
14
|
const PLUGIN_ID = 'jupyterlab_claude_code_extension:plugin';
|
|
15
15
|
const WIDGET_ID = 'jupyterlab-claude-code-extension';
|
|
@@ -59,9 +59,10 @@ const plugin: JupyterFrontEndPlugin<void> = {
|
|
|
59
59
|
try {
|
|
60
60
|
const settings = await settingRegistry.load(PLUGIN_ID);
|
|
61
61
|
const apply = (): void => {
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
const mode = settings.get('presentationMode').composite as string;
|
|
63
|
+
if (mode === 'session' || mode === 'folder' || mode === 'path') {
|
|
64
|
+
widget.setPresentationMode(mode as PresentationMode);
|
|
65
|
+
}
|
|
65
66
|
const limit = settings.get('recentLimit').composite as number;
|
|
66
67
|
if (typeof limit === 'number') {
|
|
67
68
|
widget.setRecentLimit(limit);
|
package/src/widget.ts
CHANGED
|
@@ -28,6 +28,10 @@ const EXPANDED_STORAGE_KEY = 'jupyterlab_claude_code_extension:expanded';
|
|
|
28
28
|
|
|
29
29
|
type SectionKey = 'favourites' | 'recent' | 'all';
|
|
30
30
|
|
|
31
|
+
export type PresentationMode = 'session' | 'folder' | 'path';
|
|
32
|
+
|
|
33
|
+
const DEFAULT_PRESENTATION_MODE: PresentationMode = 'session';
|
|
34
|
+
|
|
31
35
|
const SECTION_LABELS: Record<SectionKey, string> = {
|
|
32
36
|
favourites: 'Favourites',
|
|
33
37
|
recent: 'Recent',
|
|
@@ -113,12 +117,12 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
113
117
|
.finally(() => this._setRefreshSpinning(false));
|
|
114
118
|
}
|
|
115
119
|
|
|
116
|
-
/**
|
|
117
|
-
|
|
118
|
-
if (this.
|
|
120
|
+
/** Choose how rows are labelled: by session name, folder name, or path. */
|
|
121
|
+
setPresentationMode(mode: PresentationMode): void {
|
|
122
|
+
if (this._presentationMode === mode) {
|
|
119
123
|
return;
|
|
120
124
|
}
|
|
121
|
-
this.
|
|
125
|
+
this._presentationMode = mode;
|
|
122
126
|
this._render();
|
|
123
127
|
}
|
|
124
128
|
|
|
@@ -501,12 +505,19 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
501
505
|
|
|
502
506
|
// -------------------------------------------------------------- rendering
|
|
503
507
|
|
|
504
|
-
/** Apply the
|
|
508
|
+
/** Apply the presentation-mode setting (path-segment disambiguation is
|
|
509
|
+
* handled separately in ``_disambiguate``). */
|
|
505
510
|
private _displayName(s: ISession): string {
|
|
506
|
-
|
|
507
|
-
|
|
511
|
+
const folder = this._basename(s.project_path) || s.encoded_path;
|
|
512
|
+
switch (this._presentationMode) {
|
|
513
|
+
case 'folder':
|
|
514
|
+
return folder;
|
|
515
|
+
case 'path':
|
|
516
|
+
return this._displayPath(s.project_path) || folder;
|
|
517
|
+
case 'session':
|
|
518
|
+
default:
|
|
519
|
+
return s.name || folder;
|
|
508
520
|
}
|
|
509
|
-
return s.name || this._basename(s.project_path) || s.encoded_path;
|
|
510
521
|
}
|
|
511
522
|
|
|
512
523
|
private _basename(p: string): string {
|
|
@@ -649,7 +660,7 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
649
660
|
list.appendChild(empty);
|
|
650
661
|
} else {
|
|
651
662
|
for (const item of items) {
|
|
652
|
-
list.appendChild(this._renderRow(item));
|
|
663
|
+
list.appendChild(this._renderRow(item, key));
|
|
653
664
|
}
|
|
654
665
|
}
|
|
655
666
|
section.appendChild(list);
|
|
@@ -658,7 +669,7 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
658
669
|
this._bodyEl.appendChild(section);
|
|
659
670
|
}
|
|
660
671
|
|
|
661
|
-
private _renderRow(session: ISession): HTMLDivElement {
|
|
672
|
+
private _renderRow(session: ISession, sectionKey: SectionKey): HTMLDivElement {
|
|
662
673
|
const row = document.createElement('div');
|
|
663
674
|
row.className = 'jp-ClaudeSessionsPanel-row';
|
|
664
675
|
row.title = this._buildRowTooltip(session);
|
|
@@ -689,7 +700,9 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
689
700
|
name.textContent = this._lookupName(session);
|
|
690
701
|
row.appendChild(name);
|
|
691
702
|
|
|
692
|
-
|
|
703
|
+
// No star in the Favourites section - every row there is a favourite
|
|
704
|
+
// by definition; stars are an indicator only useful in Recent/All.
|
|
705
|
+
if (session.favourite && sectionKey !== 'favourites') {
|
|
693
706
|
const star = document.createElement('span');
|
|
694
707
|
star.className = 'jp-ClaudeSessionsPanel-favStar';
|
|
695
708
|
star.title = 'Favourite';
|
|
@@ -904,7 +917,7 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
904
917
|
private readonly _terminalsByPath: Map<string, any> = new Map();
|
|
905
918
|
private readonly _pendingByPath: Map<string, Promise<void>> = new Map();
|
|
906
919
|
private readonly _rootDir: string;
|
|
907
|
-
private
|
|
920
|
+
private _presentationMode: PresentationMode = DEFAULT_PRESENTATION_MODE;
|
|
908
921
|
private _recentLimit: number = DEFAULT_RECENT_LIMIT;
|
|
909
922
|
private _dangerouslySkip: boolean = false;
|
|
910
923
|
private _displayNames: Map<string, string> = new Map();
|