jupyterlab_claude_code_extension 1.0.58 → 1.0.60
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/widget.d.ts +4 -0
- package/lib/widget.js +72 -2
- package/package.json +1 -1
- package/src/widget.ts +84 -2
package/lib/widget.d.ts
CHANGED
|
@@ -73,6 +73,10 @@ export declare class ClaudeCodeSessionsWidget extends Widget {
|
|
|
73
73
|
private _lookupName;
|
|
74
74
|
private _buildRowTooltip;
|
|
75
75
|
private _displayPath;
|
|
76
|
+
/** Path relative to the JupyterLab server root (``''`` for the root
|
|
77
|
+
* itself), or ``null`` when the folder lies outside the root - in which
|
|
78
|
+
* case the file browser has no way to address it. */
|
|
79
|
+
private _pathUnderRoot;
|
|
76
80
|
private _formatRelativeTime;
|
|
77
81
|
private _setRefreshSpinning;
|
|
78
82
|
private _setActiveRow;
|
package/lib/widget.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Dialog, showDialog } from '@jupyterlab/apputils';
|
|
1
|
+
import { Clipboard, Dialog, Notification, showDialog } from '@jupyterlab/apputils';
|
|
2
|
+
import { folderIcon, terminalIcon } from '@jupyterlab/ui-components';
|
|
2
3
|
import { CommandRegistry } from '@lumino/commands';
|
|
3
4
|
import { Menu, Widget } from '@lumino/widgets';
|
|
4
5
|
import { requestAPI } from './request';
|
|
@@ -745,6 +746,21 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
745
746
|
}
|
|
746
747
|
return absolute;
|
|
747
748
|
}
|
|
749
|
+
/** Path relative to the JupyterLab server root (``''`` for the root
|
|
750
|
+
* itself), or ``null`` when the folder lies outside the root - in which
|
|
751
|
+
* case the file browser has no way to address it. */
|
|
752
|
+
_pathUnderRoot(absolute) {
|
|
753
|
+
if (!this._rootDir) {
|
|
754
|
+
return null;
|
|
755
|
+
}
|
|
756
|
+
if (absolute === this._rootDir) {
|
|
757
|
+
return '';
|
|
758
|
+
}
|
|
759
|
+
if (absolute.startsWith(this._rootDir + '/')) {
|
|
760
|
+
return absolute.slice(this._rootDir.length + 1);
|
|
761
|
+
}
|
|
762
|
+
return null;
|
|
763
|
+
}
|
|
748
764
|
_formatRelativeTime(epochMs) {
|
|
749
765
|
if (!epochMs) {
|
|
750
766
|
return 'unknown';
|
|
@@ -796,7 +812,7 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
796
812
|
}
|
|
797
813
|
});
|
|
798
814
|
this._commands.addCommand('claude-code-sessions:resume', {
|
|
799
|
-
label: 'Resume
|
|
815
|
+
label: 'Resume',
|
|
800
816
|
execute: () => {
|
|
801
817
|
if (this._activeSession) {
|
|
802
818
|
void this._resumeInTerminal(this._activeSession);
|
|
@@ -812,6 +828,53 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
812
828
|
}
|
|
813
829
|
}
|
|
814
830
|
});
|
|
831
|
+
this._commands.addCommand('claude-code-sessions:open-terminal', {
|
|
832
|
+
label: 'Open Terminal',
|
|
833
|
+
icon: terminalIcon,
|
|
834
|
+
execute: () => {
|
|
835
|
+
if (!this._activeSession) {
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
838
|
+
// JupyterLab's built-in command - spawns a fresh pty with the user's
|
|
839
|
+
// shell at the given cwd. No claude, no waiter wrapper, no reuse;
|
|
840
|
+
// for when the user wants a plain shell at the project folder.
|
|
841
|
+
void this._app.commands.execute('terminal:create-new', {
|
|
842
|
+
cwd: this._activeSession.project_path
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
});
|
|
846
|
+
this._commands.addCommand('claude-code-sessions:show-in-filebrowser', {
|
|
847
|
+
label: 'Show in File Browser',
|
|
848
|
+
icon: folderIcon,
|
|
849
|
+
execute: () => {
|
|
850
|
+
if (!this._activeSession) {
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
const rel = this._pathUnderRoot(this._activeSession.project_path);
|
|
854
|
+
if (rel === null) {
|
|
855
|
+
// The file browser can only navigate within the JupyterLab server
|
|
856
|
+
// root; a project folder outside it has no addressable path there.
|
|
857
|
+
Notification.warning('Folder is outside the JupyterLab root - the file browser cannot show it.', { autoClose: 4000 });
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
// JL's built-in command navigates the default file browser to the
|
|
861
|
+
// path and reveals the browser panel.
|
|
862
|
+
void this._app.commands.execute('filebrowser:go-to-path', {
|
|
863
|
+
path: rel
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
});
|
|
867
|
+
this._commands.addCommand('claude-code-sessions:copy-path', {
|
|
868
|
+
label: 'Copy Path',
|
|
869
|
+
execute: () => {
|
|
870
|
+
if (!this._activeSession) {
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
const path = this._activeSession.project_path;
|
|
874
|
+
Clipboard.copyToSystem(path);
|
|
875
|
+
Notification.success(`Copied: ${path}`, { autoClose: 2000 });
|
|
876
|
+
}
|
|
877
|
+
});
|
|
815
878
|
this._commands.addCommand('claude-code-sessions:remove', {
|
|
816
879
|
label: 'Remove from Claude',
|
|
817
880
|
icon: removeIcon,
|
|
@@ -827,9 +890,16 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
827
890
|
this._contextMenu.addItem({
|
|
828
891
|
command: 'claude-code-sessions:resume-dangerous'
|
|
829
892
|
});
|
|
893
|
+
this._contextMenu.addItem({
|
|
894
|
+
command: 'claude-code-sessions:open-terminal'
|
|
895
|
+
});
|
|
896
|
+
this._contextMenu.addItem({
|
|
897
|
+
command: 'claude-code-sessions:show-in-filebrowser'
|
|
898
|
+
});
|
|
830
899
|
this._contextMenu.addItem({
|
|
831
900
|
command: 'claude-code-sessions:toggle-favourite'
|
|
832
901
|
});
|
|
902
|
+
this._contextMenu.addItem({ command: 'claude-code-sessions:copy-path' });
|
|
833
903
|
this._contextMenu.addItem({ type: 'separator' });
|
|
834
904
|
this._contextMenu.addItem({ command: 'claude-code-sessions:remove' });
|
|
835
905
|
this._contextMenu.aboutToClose.connect(() => {
|
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.60",
|
|
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/widget.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { JupyterFrontEnd } from '@jupyterlab/application';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Clipboard,
|
|
4
|
+
Dialog,
|
|
5
|
+
Notification,
|
|
6
|
+
showDialog
|
|
7
|
+
} from '@jupyterlab/apputils';
|
|
3
8
|
import { ServerConnection } from '@jupyterlab/services';
|
|
4
9
|
import { ITerminalTracker } from '@jupyterlab/terminal';
|
|
10
|
+
import { folderIcon, terminalIcon } from '@jupyterlab/ui-components';
|
|
5
11
|
import { CommandRegistry } from '@lumino/commands';
|
|
6
12
|
import { Menu, Widget } from '@lumino/widgets';
|
|
7
13
|
import { Message } from '@lumino/messaging';
|
|
@@ -874,6 +880,22 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
874
880
|
return absolute;
|
|
875
881
|
}
|
|
876
882
|
|
|
883
|
+
/** Path relative to the JupyterLab server root (``''`` for the root
|
|
884
|
+
* itself), or ``null`` when the folder lies outside the root - in which
|
|
885
|
+
* case the file browser has no way to address it. */
|
|
886
|
+
private _pathUnderRoot(absolute: string): string | null {
|
|
887
|
+
if (!this._rootDir) {
|
|
888
|
+
return null;
|
|
889
|
+
}
|
|
890
|
+
if (absolute === this._rootDir) {
|
|
891
|
+
return '';
|
|
892
|
+
}
|
|
893
|
+
if (absolute.startsWith(this._rootDir + '/')) {
|
|
894
|
+
return absolute.slice(this._rootDir.length + 1);
|
|
895
|
+
}
|
|
896
|
+
return null;
|
|
897
|
+
}
|
|
898
|
+
|
|
877
899
|
private _formatRelativeTime(epochMs: number): string {
|
|
878
900
|
if (!epochMs) {
|
|
879
901
|
return 'unknown';
|
|
@@ -929,7 +951,7 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
929
951
|
});
|
|
930
952
|
|
|
931
953
|
this._commands.addCommand('claude-code-sessions:resume', {
|
|
932
|
-
label: 'Resume
|
|
954
|
+
label: 'Resume',
|
|
933
955
|
execute: () => {
|
|
934
956
|
if (this._activeSession) {
|
|
935
957
|
void this._resumeInTerminal(this._activeSession);
|
|
@@ -947,6 +969,59 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
947
969
|
}
|
|
948
970
|
});
|
|
949
971
|
|
|
972
|
+
this._commands.addCommand('claude-code-sessions:open-terminal', {
|
|
973
|
+
label: 'Open Terminal',
|
|
974
|
+
icon: terminalIcon,
|
|
975
|
+
execute: () => {
|
|
976
|
+
if (!this._activeSession) {
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
979
|
+
// JupyterLab's built-in command - spawns a fresh pty with the user's
|
|
980
|
+
// shell at the given cwd. No claude, no waiter wrapper, no reuse;
|
|
981
|
+
// for when the user wants a plain shell at the project folder.
|
|
982
|
+
void this._app.commands.execute('terminal:create-new', {
|
|
983
|
+
cwd: this._activeSession.project_path
|
|
984
|
+
});
|
|
985
|
+
}
|
|
986
|
+
});
|
|
987
|
+
|
|
988
|
+
this._commands.addCommand('claude-code-sessions:show-in-filebrowser', {
|
|
989
|
+
label: 'Show in File Browser',
|
|
990
|
+
icon: folderIcon,
|
|
991
|
+
execute: () => {
|
|
992
|
+
if (!this._activeSession) {
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
const rel = this._pathUnderRoot(this._activeSession.project_path);
|
|
996
|
+
if (rel === null) {
|
|
997
|
+
// The file browser can only navigate within the JupyterLab server
|
|
998
|
+
// root; a project folder outside it has no addressable path there.
|
|
999
|
+
Notification.warning(
|
|
1000
|
+
'Folder is outside the JupyterLab root - the file browser cannot show it.',
|
|
1001
|
+
{ autoClose: 4000 }
|
|
1002
|
+
);
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
// JL's built-in command navigates the default file browser to the
|
|
1006
|
+
// path and reveals the browser panel.
|
|
1007
|
+
void this._app.commands.execute('filebrowser:go-to-path', {
|
|
1008
|
+
path: rel
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
});
|
|
1012
|
+
|
|
1013
|
+
this._commands.addCommand('claude-code-sessions:copy-path', {
|
|
1014
|
+
label: 'Copy Path',
|
|
1015
|
+
execute: () => {
|
|
1016
|
+
if (!this._activeSession) {
|
|
1017
|
+
return;
|
|
1018
|
+
}
|
|
1019
|
+
const path = this._activeSession.project_path;
|
|
1020
|
+
Clipboard.copyToSystem(path);
|
|
1021
|
+
Notification.success(`Copied: ${path}`, { autoClose: 2000 });
|
|
1022
|
+
}
|
|
1023
|
+
});
|
|
1024
|
+
|
|
950
1025
|
this._commands.addCommand('claude-code-sessions:remove', {
|
|
951
1026
|
label: 'Remove from Claude',
|
|
952
1027
|
icon: removeIcon,
|
|
@@ -963,9 +1038,16 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
963
1038
|
this._contextMenu.addItem({
|
|
964
1039
|
command: 'claude-code-sessions:resume-dangerous'
|
|
965
1040
|
});
|
|
1041
|
+
this._contextMenu.addItem({
|
|
1042
|
+
command: 'claude-code-sessions:open-terminal'
|
|
1043
|
+
});
|
|
1044
|
+
this._contextMenu.addItem({
|
|
1045
|
+
command: 'claude-code-sessions:show-in-filebrowser'
|
|
1046
|
+
});
|
|
966
1047
|
this._contextMenu.addItem({
|
|
967
1048
|
command: 'claude-code-sessions:toggle-favourite'
|
|
968
1049
|
});
|
|
1050
|
+
this._contextMenu.addItem({ command: 'claude-code-sessions:copy-path' });
|
|
969
1051
|
this._contextMenu.addItem({ type: 'separator' });
|
|
970
1052
|
this._contextMenu.addItem({ command: 'claude-code-sessions:remove' });
|
|
971
1053
|
|