jupyterlab_claude_code_extension 1.0.45 → 1.0.50
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 +47 -15
- package/package.json +1 -1
- package/src/widget.ts +56 -19
- package/style/base.css +23 -0
package/lib/widget.d.ts
CHANGED
|
@@ -40,6 +40,10 @@ export declare class ClaudeCodeSessionsWidget extends Widget {
|
|
|
40
40
|
private _doResumeInTerminal;
|
|
41
41
|
private _findTerminalForCwd;
|
|
42
42
|
private _showCloseExistingDialog;
|
|
43
|
+
/** Show a modal with a spinner while the terminal is being launched. The
|
|
44
|
+
* caller must dismiss it via ``.resolve()`` once the work is done.
|
|
45
|
+
*/
|
|
46
|
+
private _showLaunchSpinner;
|
|
43
47
|
private _wireTerminalDisposal;
|
|
44
48
|
/** Apply the presentation-mode setting (path-segment disambiguation is
|
|
45
49
|
* handled separately in ``_disambiguate``). */
|
package/lib/widget.js
CHANGED
|
@@ -338,21 +338,29 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
338
338
|
// as the pty's only process (no shell). Server-side endpoint calls
|
|
339
339
|
// terminal_manager.create(shell_command=[claude, --resume, sid], cwd=...)
|
|
340
340
|
// and returns the terminal name; we then attach JL's standard widget
|
|
341
|
-
// via terminal:open. When claude exits, the tab closes.
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
this.
|
|
355
|
-
|
|
341
|
+
// via terminal:open. When claude exits, the tab closes. The launch
|
|
342
|
+
// RPC + the WebSocket-resize waiter on the server can take a few
|
|
343
|
+
// seconds, so show a modal spinner for visual feedback.
|
|
344
|
+
const spinner = this._showLaunchSpinner(`Opening ${this._lookupName(session)}...`);
|
|
345
|
+
try {
|
|
346
|
+
const launched = await requestAPI('launch-terminal', this._serverSettings, {
|
|
347
|
+
method: 'POST',
|
|
348
|
+
body: JSON.stringify({
|
|
349
|
+
project_path: session.project_path,
|
|
350
|
+
session_id: session.session_id,
|
|
351
|
+
dangerously_skip_permissions: forceDangerous || this._dangerouslySkip
|
|
352
|
+
})
|
|
353
|
+
});
|
|
354
|
+
const widget = await this._app.commands.execute('terminal:open', {
|
|
355
|
+
name: launched.terminal_name
|
|
356
|
+
});
|
|
357
|
+
if (widget === null || widget === void 0 ? void 0 : widget.id) {
|
|
358
|
+
this._terminalsByPath.set(session.project_path, widget);
|
|
359
|
+
this._wireTerminalDisposal(session.project_path, widget);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
finally {
|
|
363
|
+
spinner.resolve();
|
|
356
364
|
}
|
|
357
365
|
}
|
|
358
366
|
catch (err) {
|
|
@@ -407,6 +415,30 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
407
415
|
buttons: [Dialog.okButton({ label: 'OK' })]
|
|
408
416
|
});
|
|
409
417
|
}
|
|
418
|
+
/** Show a modal with a spinner while the terminal is being launched. The
|
|
419
|
+
* caller must dismiss it via ``.resolve()`` once the work is done.
|
|
420
|
+
*/
|
|
421
|
+
_showLaunchSpinner(label) {
|
|
422
|
+
const body = new Widget();
|
|
423
|
+
body.node.className = 'jp-ClaudeSessionsPanel-launchOverlay';
|
|
424
|
+
const spinner = document.createElement('div');
|
|
425
|
+
spinner.className =
|
|
426
|
+
'jp-claude-sessions-panel-spinner jp-ClaudeSessionsPanel-launchSpinner';
|
|
427
|
+
body.node.appendChild(spinner);
|
|
428
|
+
const text = document.createElement('div');
|
|
429
|
+
text.className = 'jp-ClaudeSessionsPanel-launchLabel';
|
|
430
|
+
text.textContent = label;
|
|
431
|
+
body.node.appendChild(text);
|
|
432
|
+
const dialog = new Dialog({
|
|
433
|
+
title: 'Opening Claude Code session',
|
|
434
|
+
body,
|
|
435
|
+
buttons: [Dialog.cancelButton({ label: 'Run in background' })]
|
|
436
|
+
});
|
|
437
|
+
// launch() returns a Promise we don't await - we resolve programmatically
|
|
438
|
+
// when the spawn completes (or errors).
|
|
439
|
+
void dialog.launch();
|
|
440
|
+
return dialog;
|
|
441
|
+
}
|
|
410
442
|
_wireTerminalDisposal(projectPath, widget) {
|
|
411
443
|
var _a;
|
|
412
444
|
if (!((_a = widget === null || widget === void 0 ? void 0 : widget.disposed) === null || _a === void 0 ? void 0 : _a.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.50",
|
|
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
|
@@ -415,26 +415,35 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
415
415
|
// as the pty's only process (no shell). Server-side endpoint calls
|
|
416
416
|
// terminal_manager.create(shell_command=[claude, --resume, sid], cwd=...)
|
|
417
417
|
// and returns the terminal name; we then attach JL's standard widget
|
|
418
|
-
// via terminal:open. When claude exits, the tab closes.
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
{
|
|
423
|
-
method: 'POST',
|
|
424
|
-
body: JSON.stringify({
|
|
425
|
-
project_path: session.project_path,
|
|
426
|
-
session_id: session.session_id,
|
|
427
|
-
dangerously_skip_permissions:
|
|
428
|
-
forceDangerous || this._dangerouslySkip
|
|
429
|
-
})
|
|
430
|
-
}
|
|
418
|
+
// via terminal:open. When claude exits, the tab closes. The launch
|
|
419
|
+
// RPC + the WebSocket-resize waiter on the server can take a few
|
|
420
|
+
// seconds, so show a modal spinner for visual feedback.
|
|
421
|
+
const spinner = this._showLaunchSpinner(
|
|
422
|
+
`Opening ${this._lookupName(session)}...`
|
|
431
423
|
);
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
424
|
+
try {
|
|
425
|
+
const launched = await requestAPI<ILaunchTerminalResponse>(
|
|
426
|
+
'launch-terminal',
|
|
427
|
+
this._serverSettings,
|
|
428
|
+
{
|
|
429
|
+
method: 'POST',
|
|
430
|
+
body: JSON.stringify({
|
|
431
|
+
project_path: session.project_path,
|
|
432
|
+
session_id: session.session_id,
|
|
433
|
+
dangerously_skip_permissions:
|
|
434
|
+
forceDangerous || this._dangerouslySkip
|
|
435
|
+
})
|
|
436
|
+
}
|
|
437
|
+
);
|
|
438
|
+
const widget: any = await this._app.commands.execute('terminal:open', {
|
|
439
|
+
name: launched.terminal_name
|
|
440
|
+
});
|
|
441
|
+
if (widget?.id) {
|
|
442
|
+
this._terminalsByPath.set(session.project_path, widget);
|
|
443
|
+
this._wireTerminalDisposal(session.project_path, widget);
|
|
444
|
+
}
|
|
445
|
+
} finally {
|
|
446
|
+
spinner.resolve();
|
|
438
447
|
}
|
|
439
448
|
} catch (err) {
|
|
440
449
|
this._showError(err);
|
|
@@ -493,6 +502,34 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
493
502
|
});
|
|
494
503
|
}
|
|
495
504
|
|
|
505
|
+
/** Show a modal with a spinner while the terminal is being launched. The
|
|
506
|
+
* caller must dismiss it via ``.resolve()`` once the work is done.
|
|
507
|
+
*/
|
|
508
|
+
private _showLaunchSpinner(label: string): Dialog<unknown> {
|
|
509
|
+
const body = new Widget();
|
|
510
|
+
body.node.className = 'jp-ClaudeSessionsPanel-launchOverlay';
|
|
511
|
+
|
|
512
|
+
const spinner = document.createElement('div');
|
|
513
|
+
spinner.className =
|
|
514
|
+
'jp-claude-sessions-panel-spinner jp-ClaudeSessionsPanel-launchSpinner';
|
|
515
|
+
body.node.appendChild(spinner);
|
|
516
|
+
|
|
517
|
+
const text = document.createElement('div');
|
|
518
|
+
text.className = 'jp-ClaudeSessionsPanel-launchLabel';
|
|
519
|
+
text.textContent = label;
|
|
520
|
+
body.node.appendChild(text);
|
|
521
|
+
|
|
522
|
+
const dialog = new Dialog<unknown>({
|
|
523
|
+
title: 'Opening Claude Code session',
|
|
524
|
+
body,
|
|
525
|
+
buttons: [Dialog.cancelButton({ label: 'Run in background' })]
|
|
526
|
+
});
|
|
527
|
+
// launch() returns a Promise we don't await - we resolve programmatically
|
|
528
|
+
// when the spawn completes (or errors).
|
|
529
|
+
void dialog.launch();
|
|
530
|
+
return dialog;
|
|
531
|
+
}
|
|
532
|
+
|
|
496
533
|
private _wireTerminalDisposal(projectPath: string, widget: any): void {
|
|
497
534
|
if (!widget?.disposed?.connect) {
|
|
498
535
|
return;
|
package/style/base.css
CHANGED
|
@@ -237,6 +237,29 @@
|
|
|
237
237
|
display: inline-block;
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
+
.jp-ClaudeSessionsPanel-launchOverlay {
|
|
241
|
+
display: flex;
|
|
242
|
+
flex-direction: column;
|
|
243
|
+
align-items: center;
|
|
244
|
+
justify-content: center;
|
|
245
|
+
gap: 12px;
|
|
246
|
+
padding: 12px 8px;
|
|
247
|
+
min-width: 240px;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.jp-ClaudeSessionsPanel-launchSpinner {
|
|
251
|
+
width: 28px;
|
|
252
|
+
height: 28px;
|
|
253
|
+
border-width: 3px;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.jp-ClaudeSessionsPanel-launchLabel {
|
|
257
|
+
font-size: var(--jp-ui-font-size1);
|
|
258
|
+
color: var(--jp-ui-font-color1);
|
|
259
|
+
text-align: center;
|
|
260
|
+
word-break: break-word;
|
|
261
|
+
}
|
|
262
|
+
|
|
240
263
|
.jp-ClaudeSessionsPanel-row.jp-mod-busy {
|
|
241
264
|
opacity: 0.55;
|
|
242
265
|
pointer-events: none;
|