jupyterlab_claude_code_extension 1.0.19 → 1.0.26
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 +7 -0
- package/lib/index.js +3 -0
- package/lib/types.d.ts +1 -0
- package/lib/widget.d.ts +16 -1
- package/lib/widget.js +84 -13
- package/package.json +1 -1
- package/src/icons.ts +9 -0
- package/src/index.ts +3 -0
- package/src/types.ts +1 -0
- package/src/widget.ts +105 -15
package/lib/icons.d.ts
CHANGED
package/lib/icons.js
CHANGED
|
@@ -42,3 +42,10 @@ export const removeIcon = new LabIcon({
|
|
|
42
42
|
name: 'jupyterlab_claude_code_extension:remove',
|
|
43
43
|
svgstr: removeSvgStr
|
|
44
44
|
});
|
|
45
|
+
const shieldSvgStr = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16">
|
|
46
|
+
<path class="jp-icon3" fill="#616161" d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z"/>
|
|
47
|
+
</svg>`;
|
|
48
|
+
export const shieldIcon = new LabIcon({
|
|
49
|
+
name: 'jupyterlab_claude_code_extension:shield',
|
|
50
|
+
svgstr: shieldSvgStr
|
|
51
|
+
});
|
package/lib/index.js
CHANGED
|
@@ -38,6 +38,9 @@ const plugin = {
|
|
|
38
38
|
if (typeof limit === 'number') {
|
|
39
39
|
widget.setRecentLimit(limit);
|
|
40
40
|
}
|
|
41
|
+
const dangerous = settings.get('dangerouslySkipPermissions')
|
|
42
|
+
.composite;
|
|
43
|
+
widget.setDangerouslySkipPermissions(!!dangerous);
|
|
41
44
|
};
|
|
42
45
|
apply();
|
|
43
46
|
settings.changed.connect(apply);
|
package/lib/types.d.ts
CHANGED
package/lib/widget.d.ts
CHANGED
|
@@ -9,12 +9,26 @@ export declare class ClaudeCodeSessionsWidget extends Widget {
|
|
|
9
9
|
setResolveSessionNames(on: boolean): void;
|
|
10
10
|
/** Set how many rows the Recent section displays. */
|
|
11
11
|
setRecentLimit(n: number): void;
|
|
12
|
+
/** Toggle the --dangerously-skip-permissions flag on launched sessions. */
|
|
13
|
+
setDangerouslySkipPermissions(on: boolean): void;
|
|
12
14
|
protected onAfterShow(_msg: Message): void;
|
|
13
15
|
protected onBeforeHide(_msg: Message): void;
|
|
14
16
|
protected onCloseRequest(msg: Message): void;
|
|
15
17
|
private _buildShell;
|
|
16
|
-
/**
|
|
18
|
+
/** Normalise strings for filter comparison: NFD-decompose, strip combining
|
|
19
|
+
* diacritic marks, lowercase, and collapse separators (`-`, `_`, `.`, `/`,
|
|
20
|
+
* whitespace) entirely. So "foo-bar", "foo_bar", "foo bar", "Foo Bar" all
|
|
21
|
+
* compare equal as "foobar".
|
|
22
|
+
*/
|
|
23
|
+
private _normalize;
|
|
24
|
+
/** Fuzzy match at a 95% threshold: substring on normalised strings,
|
|
25
|
+
* with up to 5% Levenshtein tolerance. For short queries the budget
|
|
26
|
+
* still rounds to zero so behaviour is substring-only there - the
|
|
27
|
+
* relaxation only kicks in for queries long enough that 5% reaches a
|
|
28
|
+
* full edit (10+ chars).
|
|
29
|
+
*/
|
|
17
30
|
private _fuzzyMatch;
|
|
31
|
+
private _levenshtein;
|
|
18
32
|
private _matchesFilter;
|
|
19
33
|
private _showLoading;
|
|
20
34
|
private _showError;
|
|
@@ -61,6 +75,7 @@ export declare class ClaudeCodeSessionsWidget extends Widget {
|
|
|
61
75
|
private readonly _rootDir;
|
|
62
76
|
private _resolveNames;
|
|
63
77
|
private _recentLimit;
|
|
78
|
+
private _dangerouslySkip;
|
|
64
79
|
private _displayNames;
|
|
65
80
|
private _filter;
|
|
66
81
|
}
|
package/lib/widget.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CommandRegistry } from '@lumino/commands';
|
|
2
2
|
import { Menu, Widget } from '@lumino/widgets';
|
|
3
3
|
import { requestAPI } from './request';
|
|
4
|
-
import { claudeIcon, refreshIcon, removeIcon, starFilledIcon } from './icons';
|
|
4
|
+
import { claudeIcon, refreshIcon, removeIcon, shieldIcon, starFilledIcon } from './icons';
|
|
5
5
|
const POLL_INTERVAL_MS = 10000;
|
|
6
6
|
const DEFAULT_RECENT_LIMIT = 10;
|
|
7
7
|
const EXPANDED_STORAGE_KEY = 'jupyterlab_claude_code_extension:expanded';
|
|
@@ -66,6 +66,7 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
66
66
|
this._pendingByPath = new Map();
|
|
67
67
|
this._resolveNames = true;
|
|
68
68
|
this._recentLimit = DEFAULT_RECENT_LIMIT;
|
|
69
|
+
this._dangerouslySkip = false;
|
|
69
70
|
this._displayNames = new Map();
|
|
70
71
|
this._filter = '';
|
|
71
72
|
this._app = app;
|
|
@@ -103,6 +104,10 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
103
104
|
this._recentLimit = clamped;
|
|
104
105
|
this._render();
|
|
105
106
|
}
|
|
107
|
+
/** Toggle the --dangerously-skip-permissions flag on launched sessions. */
|
|
108
|
+
setDangerouslySkipPermissions(on) {
|
|
109
|
+
this._dangerouslySkip = !!on;
|
|
110
|
+
}
|
|
106
111
|
onAfterShow(_msg) {
|
|
107
112
|
this.refresh();
|
|
108
113
|
this._startPolling();
|
|
@@ -151,23 +156,76 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
151
156
|
this._bodyEl = body;
|
|
152
157
|
this._statusEl = status;
|
|
153
158
|
}
|
|
154
|
-
/**
|
|
159
|
+
/** Normalise strings for filter comparison: NFD-decompose, strip combining
|
|
160
|
+
* diacritic marks, lowercase, and collapse separators (`-`, `_`, `.`, `/`,
|
|
161
|
+
* whitespace) entirely. So "foo-bar", "foo_bar", "foo bar", "Foo Bar" all
|
|
162
|
+
* compare equal as "foobar".
|
|
163
|
+
*/
|
|
164
|
+
_normalize(s) {
|
|
165
|
+
return s
|
|
166
|
+
.normalize('NFD')
|
|
167
|
+
.replace(/[̀-ͯ]/g, '')
|
|
168
|
+
.toLowerCase()
|
|
169
|
+
.replace(/[\s\-_./]+/g, '');
|
|
170
|
+
}
|
|
171
|
+
/** Fuzzy match at a 95% threshold: substring on normalised strings,
|
|
172
|
+
* with up to 5% Levenshtein tolerance. For short queries the budget
|
|
173
|
+
* still rounds to zero so behaviour is substring-only there - the
|
|
174
|
+
* relaxation only kicks in for queries long enough that 5% reaches a
|
|
175
|
+
* full edit (10+ chars).
|
|
176
|
+
*/
|
|
155
177
|
_fuzzyMatch(haystack, needle) {
|
|
156
178
|
if (!needle) {
|
|
157
179
|
return true;
|
|
158
180
|
}
|
|
159
|
-
const h =
|
|
160
|
-
const n =
|
|
181
|
+
const h = this._normalize(haystack);
|
|
182
|
+
const n = this._normalize(needle);
|
|
183
|
+
if (!n) {
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
161
186
|
if (h.includes(n)) {
|
|
162
187
|
return true;
|
|
163
188
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
189
|
+
const tol = Math.round(n.length * 0.05);
|
|
190
|
+
if (tol === 0) {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
for (let len = n.length - tol; len <= n.length + tol; len += 1) {
|
|
194
|
+
if (len <= 0) {
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
for (let i = 0; i + len <= h.length; i += 1) {
|
|
198
|
+
if (this._levenshtein(h.slice(i, i + len), n) <= tol) {
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
_levenshtein(a, b) {
|
|
206
|
+
const m = a.length;
|
|
207
|
+
const n = b.length;
|
|
208
|
+
if (m === 0) {
|
|
209
|
+
return n;
|
|
210
|
+
}
|
|
211
|
+
if (n === 0) {
|
|
212
|
+
return m;
|
|
213
|
+
}
|
|
214
|
+
const dp = new Array(n + 1);
|
|
215
|
+
for (let j = 0; j <= n; j += 1) {
|
|
216
|
+
dp[j] = j;
|
|
217
|
+
}
|
|
218
|
+
for (let i = 1; i <= m; i += 1) {
|
|
219
|
+
let prev = dp[0];
|
|
220
|
+
dp[0] = i;
|
|
221
|
+
for (let j = 1; j <= n; j += 1) {
|
|
222
|
+
const tmp = dp[j];
|
|
223
|
+
dp[j] =
|
|
224
|
+
a[i - 1] === b[j - 1] ? prev : 1 + Math.min(prev, dp[j], dp[j - 1]);
|
|
225
|
+
prev = tmp;
|
|
168
226
|
}
|
|
169
227
|
}
|
|
170
|
-
return
|
|
228
|
+
return dp[n];
|
|
171
229
|
}
|
|
172
230
|
_matchesFilter(s) {
|
|
173
231
|
const q = this._filter.trim();
|
|
@@ -235,20 +293,20 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
235
293
|
}
|
|
236
294
|
}
|
|
237
295
|
// -------------------------------------------------------------- terminal
|
|
238
|
-
async _resumeInTerminal(session) {
|
|
296
|
+
async _resumeInTerminal(session, forceDangerous = false) {
|
|
239
297
|
// Coalesce concurrent clicks on the same row - subsequent clicks attach
|
|
240
298
|
// to the in-flight promise instead of creating their own terminal.
|
|
241
299
|
const inFlight = this._pendingByPath.get(session.project_path);
|
|
242
300
|
if (inFlight) {
|
|
243
301
|
return inFlight;
|
|
244
302
|
}
|
|
245
|
-
const promise = this._doResumeInTerminal(session).finally(() => {
|
|
303
|
+
const promise = this._doResumeInTerminal(session, forceDangerous).finally(() => {
|
|
246
304
|
this._pendingByPath.delete(session.project_path);
|
|
247
305
|
});
|
|
248
306
|
this._pendingByPath.set(session.project_path, promise);
|
|
249
307
|
return promise;
|
|
250
308
|
}
|
|
251
|
-
async _doResumeInTerminal(session) {
|
|
309
|
+
async _doResumeInTerminal(session, forceDangerous) {
|
|
252
310
|
try {
|
|
253
311
|
// 1. In-memory microcache - covers rapid-click and post-creation reuse
|
|
254
312
|
// before the new widget propagates fully through the tracker. Cleared
|
|
@@ -277,7 +335,8 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
277
335
|
method: 'POST',
|
|
278
336
|
body: JSON.stringify({
|
|
279
337
|
project_path: session.project_path,
|
|
280
|
-
session_id: session.session_id
|
|
338
|
+
session_id: session.session_id,
|
|
339
|
+
dangerously_skip_permissions: forceDangerous || this._dangerouslySkip
|
|
281
340
|
})
|
|
282
341
|
});
|
|
283
342
|
const widget = await this._app.commands.execute('terminal:open', {
|
|
@@ -626,6 +685,15 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
626
685
|
}
|
|
627
686
|
}
|
|
628
687
|
});
|
|
688
|
+
this._commands.addCommand('claude-code-sessions:resume-dangerous', {
|
|
689
|
+
label: 'Resume (Skip Permissions)',
|
|
690
|
+
icon: shieldIcon,
|
|
691
|
+
execute: () => {
|
|
692
|
+
if (this._activeSession) {
|
|
693
|
+
void this._resumeInTerminal(this._activeSession, true);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
});
|
|
629
697
|
this._commands.addCommand('claude-code-sessions:remove', {
|
|
630
698
|
label: 'Remove from Claude',
|
|
631
699
|
icon: removeIcon,
|
|
@@ -638,6 +706,9 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
638
706
|
this._contextMenu = new Menu({ commands: this._commands });
|
|
639
707
|
this._contextMenu.addClass('jp-ClaudeSessionsContextMenu');
|
|
640
708
|
this._contextMenu.addItem({ command: 'claude-code-sessions:resume' });
|
|
709
|
+
this._contextMenu.addItem({
|
|
710
|
+
command: 'claude-code-sessions:resume-dangerous'
|
|
711
|
+
});
|
|
641
712
|
this._contextMenu.addItem({
|
|
642
713
|
command: 'claude-code-sessions:toggle-favourite'
|
|
643
714
|
});
|
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.26",
|
|
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
|
@@ -50,3 +50,12 @@ export const removeIcon = new LabIcon({
|
|
|
50
50
|
name: 'jupyterlab_claude_code_extension:remove',
|
|
51
51
|
svgstr: removeSvgStr
|
|
52
52
|
});
|
|
53
|
+
|
|
54
|
+
const shieldSvgStr = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16">
|
|
55
|
+
<path class="jp-icon3" fill="#616161" d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z"/>
|
|
56
|
+
</svg>`;
|
|
57
|
+
|
|
58
|
+
export const shieldIcon = new LabIcon({
|
|
59
|
+
name: 'jupyterlab_claude_code_extension:shield',
|
|
60
|
+
svgstr: shieldSvgStr
|
|
61
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -66,6 +66,9 @@ const plugin: JupyterFrontEndPlugin<void> = {
|
|
|
66
66
|
if (typeof limit === 'number') {
|
|
67
67
|
widget.setRecentLimit(limit);
|
|
68
68
|
}
|
|
69
|
+
const dangerous = settings.get('dangerouslySkipPermissions')
|
|
70
|
+
.composite as boolean;
|
|
71
|
+
widget.setDangerouslySkipPermissions(!!dangerous);
|
|
69
72
|
};
|
|
70
73
|
apply();
|
|
71
74
|
settings.changed.connect(apply);
|
package/src/types.ts
CHANGED
package/src/widget.ts
CHANGED
|
@@ -6,7 +6,13 @@ import { Menu, Widget } from '@lumino/widgets';
|
|
|
6
6
|
import { Message } from '@lumino/messaging';
|
|
7
7
|
|
|
8
8
|
import { requestAPI } from './request';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
claudeIcon,
|
|
11
|
+
refreshIcon,
|
|
12
|
+
removeIcon,
|
|
13
|
+
shieldIcon,
|
|
14
|
+
starFilledIcon
|
|
15
|
+
} from './icons';
|
|
10
16
|
import {
|
|
11
17
|
IFavouriteResponse,
|
|
12
18
|
ILaunchTerminalResponse,
|
|
@@ -125,6 +131,11 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
125
131
|
this._render();
|
|
126
132
|
}
|
|
127
133
|
|
|
134
|
+
/** Toggle the --dangerously-skip-permissions flag on launched sessions. */
|
|
135
|
+
setDangerouslySkipPermissions(on: boolean): void {
|
|
136
|
+
this._dangerouslySkip = !!on;
|
|
137
|
+
}
|
|
138
|
+
|
|
128
139
|
protected onAfterShow(_msg: Message): void {
|
|
129
140
|
this.refresh();
|
|
130
141
|
this._startPolling();
|
|
@@ -186,23 +197,78 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
186
197
|
this._statusEl = status;
|
|
187
198
|
}
|
|
188
199
|
|
|
189
|
-
/**
|
|
200
|
+
/** Normalise strings for filter comparison: NFD-decompose, strip combining
|
|
201
|
+
* diacritic marks, lowercase, and collapse separators (`-`, `_`, `.`, `/`,
|
|
202
|
+
* whitespace) entirely. So "foo-bar", "foo_bar", "foo bar", "Foo Bar" all
|
|
203
|
+
* compare equal as "foobar".
|
|
204
|
+
*/
|
|
205
|
+
private _normalize(s: string): string {
|
|
206
|
+
return s
|
|
207
|
+
.normalize('NFD')
|
|
208
|
+
.replace(/[̀-ͯ]/g, '')
|
|
209
|
+
.toLowerCase()
|
|
210
|
+
.replace(/[\s\-_./]+/g, '');
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** Fuzzy match at a 95% threshold: substring on normalised strings,
|
|
214
|
+
* with up to 5% Levenshtein tolerance. For short queries the budget
|
|
215
|
+
* still rounds to zero so behaviour is substring-only there - the
|
|
216
|
+
* relaxation only kicks in for queries long enough that 5% reaches a
|
|
217
|
+
* full edit (10+ chars).
|
|
218
|
+
*/
|
|
190
219
|
private _fuzzyMatch(haystack: string, needle: string): boolean {
|
|
191
220
|
if (!needle) {
|
|
192
221
|
return true;
|
|
193
222
|
}
|
|
194
|
-
const h =
|
|
195
|
-
const n =
|
|
223
|
+
const h = this._normalize(haystack);
|
|
224
|
+
const n = this._normalize(needle);
|
|
225
|
+
if (!n) {
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
196
228
|
if (h.includes(n)) {
|
|
197
229
|
return true;
|
|
198
230
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
231
|
+
const tol = Math.round(n.length * 0.05);
|
|
232
|
+
if (tol === 0) {
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
for (let len = n.length - tol; len <= n.length + tol; len += 1) {
|
|
236
|
+
if (len <= 0) {
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
for (let i = 0; i + len <= h.length; i += 1) {
|
|
240
|
+
if (this._levenshtein(h.slice(i, i + len), n) <= tol) {
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
203
243
|
}
|
|
204
244
|
}
|
|
205
|
-
return
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
private _levenshtein(a: string, b: string): number {
|
|
249
|
+
const m = a.length;
|
|
250
|
+
const n = b.length;
|
|
251
|
+
if (m === 0) {
|
|
252
|
+
return n;
|
|
253
|
+
}
|
|
254
|
+
if (n === 0) {
|
|
255
|
+
return m;
|
|
256
|
+
}
|
|
257
|
+
const dp: number[] = new Array(n + 1);
|
|
258
|
+
for (let j = 0; j <= n; j += 1) {
|
|
259
|
+
dp[j] = j;
|
|
260
|
+
}
|
|
261
|
+
for (let i = 1; i <= m; i += 1) {
|
|
262
|
+
let prev = dp[0];
|
|
263
|
+
dp[0] = i;
|
|
264
|
+
for (let j = 1; j <= n; j += 1) {
|
|
265
|
+
const tmp = dp[j];
|
|
266
|
+
dp[j] =
|
|
267
|
+
a[i - 1] === b[j - 1] ? prev : 1 + Math.min(prev, dp[j], dp[j - 1]);
|
|
268
|
+
prev = tmp;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return dp[n];
|
|
206
272
|
}
|
|
207
273
|
|
|
208
274
|
private _matchesFilter(s: ISession): boolean {
|
|
@@ -289,21 +355,29 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
289
355
|
|
|
290
356
|
// -------------------------------------------------------------- terminal
|
|
291
357
|
|
|
292
|
-
private async _resumeInTerminal(
|
|
358
|
+
private async _resumeInTerminal(
|
|
359
|
+
session: ISession,
|
|
360
|
+
forceDangerous: boolean = false
|
|
361
|
+
): Promise<void> {
|
|
293
362
|
// Coalesce concurrent clicks on the same row - subsequent clicks attach
|
|
294
363
|
// to the in-flight promise instead of creating their own terminal.
|
|
295
364
|
const inFlight = this._pendingByPath.get(session.project_path);
|
|
296
365
|
if (inFlight) {
|
|
297
366
|
return inFlight;
|
|
298
367
|
}
|
|
299
|
-
const promise = this._doResumeInTerminal(session).finally(
|
|
300
|
-
|
|
301
|
-
|
|
368
|
+
const promise = this._doResumeInTerminal(session, forceDangerous).finally(
|
|
369
|
+
() => {
|
|
370
|
+
this._pendingByPath.delete(session.project_path);
|
|
371
|
+
}
|
|
372
|
+
);
|
|
302
373
|
this._pendingByPath.set(session.project_path, promise);
|
|
303
374
|
return promise;
|
|
304
375
|
}
|
|
305
376
|
|
|
306
|
-
private async _doResumeInTerminal(
|
|
377
|
+
private async _doResumeInTerminal(
|
|
378
|
+
session: ISession,
|
|
379
|
+
forceDangerous: boolean
|
|
380
|
+
): Promise<void> {
|
|
307
381
|
try {
|
|
308
382
|
// 1. In-memory microcache - covers rapid-click and post-creation reuse
|
|
309
383
|
// before the new widget propagates fully through the tracker. Cleared
|
|
@@ -337,7 +411,9 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
337
411
|
method: 'POST',
|
|
338
412
|
body: JSON.stringify({
|
|
339
413
|
project_path: session.project_path,
|
|
340
|
-
session_id: session.session_id
|
|
414
|
+
session_id: session.session_id,
|
|
415
|
+
dangerously_skip_permissions:
|
|
416
|
+
forceDangerous || this._dangerouslySkip
|
|
341
417
|
})
|
|
342
418
|
}
|
|
343
419
|
);
|
|
@@ -724,6 +800,16 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
724
800
|
}
|
|
725
801
|
});
|
|
726
802
|
|
|
803
|
+
this._commands.addCommand('claude-code-sessions:resume-dangerous', {
|
|
804
|
+
label: 'Resume (Skip Permissions)',
|
|
805
|
+
icon: shieldIcon,
|
|
806
|
+
execute: () => {
|
|
807
|
+
if (this._activeSession) {
|
|
808
|
+
void this._resumeInTerminal(this._activeSession, true);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
});
|
|
812
|
+
|
|
727
813
|
this._commands.addCommand('claude-code-sessions:remove', {
|
|
728
814
|
label: 'Remove from Claude',
|
|
729
815
|
icon: removeIcon,
|
|
@@ -737,6 +823,9 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
737
823
|
this._contextMenu = new Menu({ commands: this._commands });
|
|
738
824
|
this._contextMenu.addClass('jp-ClaudeSessionsContextMenu');
|
|
739
825
|
this._contextMenu.addItem({ command: 'claude-code-sessions:resume' });
|
|
826
|
+
this._contextMenu.addItem({
|
|
827
|
+
command: 'claude-code-sessions:resume-dangerous'
|
|
828
|
+
});
|
|
740
829
|
this._contextMenu.addItem({
|
|
741
830
|
command: 'claude-code-sessions:toggle-favourite'
|
|
742
831
|
});
|
|
@@ -793,6 +882,7 @@ export class ClaudeCodeSessionsWidget extends Widget {
|
|
|
793
882
|
private readonly _rootDir: string;
|
|
794
883
|
private _resolveNames: boolean = true;
|
|
795
884
|
private _recentLimit: number = DEFAULT_RECENT_LIMIT;
|
|
885
|
+
private _dangerouslySkip: boolean = false;
|
|
796
886
|
private _displayNames: Map<string, string> = new Map();
|
|
797
887
|
private _filter: string = '';
|
|
798
888
|
}
|