jupyterlab_ai_code_assistants_extension 1.0.21 → 1.0.23
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/README.md +1 -1
- package/lib/core/modes.d.ts +3 -6
- package/lib/core/modes.js +11 -31
- package/lib/core/panel.d.ts +1 -3
- package/lib/core/panel.js +10 -28
- package/lib/core/types.d.ts +6 -19
- package/lib/providers/claude.js +0 -1
- package/lib/providers/codex.js +0 -1
- package/lib/providers/gemini.js +2 -14
- package/lib/providers/kimi.js +0 -1
- package/package.json +1 -1
- package/schema/plugin.json +0 -7
- package/src/__tests__/launch-mode.spec.ts +18 -54
- package/src/__tests__/panel.spec.ts +5 -8
- package/src/__tests__/registry.spec.ts +2 -7
- package/src/core/modes.ts +11 -33
- package/src/core/panel.ts +9 -30
- package/src/core/types.ts +6 -19
- package/src/providers/claude.ts +0 -1
- package/src/providers/codex.ts +0 -1
- package/src/providers/gemini.ts +2 -15
- package/src/providers/kimi.ts +0 -1
package/README.md
CHANGED
|
@@ -32,7 +32,7 @@ Chat-panel extensions re-implement the agent loop and trail the real tool. This
|
|
|
32
32
|
- **One-click resume** - click a row to jump back into that session in a terminal; an open terminal for the project is reused instead of duplicated
|
|
33
33
|
- **Conversation switcher** - a right-click "Switch and Manage Sessions" submenu lists a project's other conversations by name and short id with last-activity time; "Manage Sessions..." opens a searchable popup over the full list with multi-select delete and per-row open and copy-id buttons
|
|
34
34
|
- **Branch session** - fork the current conversation into a new named session via the right-click menu; each assistant forks its own way (Claude's native `--fork-session`, Codex's `codex fork`, server-side copies for Kimi and Gemini) behind the same menu item
|
|
35
|
-
- **Launch modes under each assistant's own name** - Claude's skip-permissions, Codex's approval bypass, Kimi's `--yolo`, Gemini's YOLO
|
|
35
|
+
- **Launch modes under each assistant's own name** - Claude's skip-permissions, Codex's approval bypass, Kimi's `--yolo`, Gemini's YOLO; unsafe variants carry a shield glyph in the launch menus
|
|
36
36
|
- **Coloured terminal tabs** - each session's colour tints its terminal tab via the companion `jupyterlab_colourful_tab_extension` (installed automatically). Claude's own `/color` supplies its default, Kimi derives a stable colour from the conversation id; Codex and Gemini have no colour of their own until you set one, and a branched session inherits its parent's colour, which it keeps even if the parent's colour later changes or is reset
|
|
37
37
|
- **Your own tab colour wins** - set a colour on a terminal tab and the extension remembers it for that conversation, overriding whatever the assistant chose. `Reset Tab Colour (n)` in the session's right-click menu hands back every colour you set by hand on that project's conversations, and appears once there is one to hand back. Use it rather than the tab menu's own Clear, which will not release a stored colour. A Codex or Kimi conversation that has never been resumed cannot be tracked yet, so a colour set on its tab is not kept
|
|
38
38
|
- **Favorites** - star projects you keep coming back to via the right-click menu; favourites from the standalone extensions are migrated on first run
|
package/lib/core/modes.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { ILaunchMode } from './types';
|
|
|
2
2
|
/** A resolved launch mode, with what to call it and whether to warn. */
|
|
3
3
|
export interface IResolvedLaunchMode {
|
|
4
4
|
mode: ILaunchMode;
|
|
5
|
-
/** What the menu should call it - the
|
|
5
|
+
/** What the menu should call it - the mode's own label. */
|
|
6
6
|
label: string;
|
|
7
7
|
/** Whether this widens what the assistant may do without asking. */
|
|
8
8
|
unsafe: boolean;
|
|
@@ -12,11 +12,8 @@ export interface IResolvedLaunchMode {
|
|
|
12
12
|
*
|
|
13
13
|
* The payload carries at most one mode, because the server maps one token to
|
|
14
14
|
* one flag. `force` wins outright - that is what the menu's variant entries
|
|
15
|
-
* do. Otherwise
|
|
16
|
-
*
|
|
17
|
-
* left on must not silently invert it. A boolean fires only while every enum
|
|
18
|
-
* mode sits at its default. An enum at its default sends nothing - it is what
|
|
19
|
-
* the CLI would do unasked.
|
|
15
|
+
* do. Otherwise the first switch that is on fires. Every mode is a boolean
|
|
16
|
+
* skip-approval switch, so "on" always means the same thing.
|
|
20
17
|
*/
|
|
21
18
|
export declare function resolveLaunchMode(launchModes: ILaunchMode[], values: Record<string, boolean | string>, force?: string): string | undefined;
|
|
22
19
|
/**
|
package/lib/core/modes.js
CHANGED
|
@@ -1,34 +1,22 @@
|
|
|
1
1
|
// Launch-mode resolution: which single mode token, if any, one launch carries.
|
|
2
2
|
//
|
|
3
3
|
// Its own module because the panel is the only caller but not the only reader -
|
|
4
|
-
// the
|
|
5
|
-
//
|
|
4
|
+
// the rule that one launch carries at most one mode is worth asserting on its
|
|
5
|
+
// own, and this file pulls in no JupyterLab surface.
|
|
6
6
|
/**
|
|
7
7
|
* The single launch-mode token for one action, or undefined for a plain launch.
|
|
8
8
|
*
|
|
9
9
|
* The payload carries at most one mode, because the server maps one token to
|
|
10
10
|
* one flag. `force` wins outright - that is what the menu's variant entries
|
|
11
|
-
* do. Otherwise
|
|
12
|
-
*
|
|
13
|
-
* left on must not silently invert it. A boolean fires only while every enum
|
|
14
|
-
* mode sits at its default. An enum at its default sends nothing - it is what
|
|
15
|
-
* the CLI would do unasked.
|
|
11
|
+
* do. Otherwise the first switch that is on fires. Every mode is a boolean
|
|
12
|
+
* skip-approval switch, so "on" always means the same thing.
|
|
16
13
|
*/
|
|
17
14
|
export function resolveLaunchMode(launchModes, values, force) {
|
|
18
15
|
if (force) {
|
|
19
16
|
return force;
|
|
20
17
|
}
|
|
21
18
|
for (const mode of launchModes) {
|
|
22
|
-
|
|
23
|
-
if (mode.kind !== 'boolean' &&
|
|
24
|
-
typeof value === 'string' &&
|
|
25
|
-
value &&
|
|
26
|
-
value !== mode.default) {
|
|
27
|
-
return `${mode.id}=${value}`;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
for (const mode of launchModes) {
|
|
31
|
-
if (mode.kind === 'boolean' && values[mode.id] === true) {
|
|
19
|
+
if (values[mode.id] === true) {
|
|
32
20
|
return mode.id;
|
|
33
21
|
}
|
|
34
22
|
}
|
|
@@ -45,28 +33,20 @@ export function resolveLaunchMode(launchModes, values, force) {
|
|
|
45
33
|
* assistant's own wording.
|
|
46
34
|
*/
|
|
47
35
|
export function resolvedLaunchModeEntry(launchModes, values) {
|
|
48
|
-
var _a
|
|
36
|
+
var _a;
|
|
49
37
|
const token = resolveLaunchMode(launchModes, values);
|
|
50
38
|
if (!token) {
|
|
51
39
|
return null;
|
|
52
40
|
}
|
|
53
|
-
const
|
|
54
|
-
const mode = launchModes.find(m => m.id === id);
|
|
41
|
+
const mode = launchModes.find(m => m.id === token);
|
|
55
42
|
if (!mode) {
|
|
56
43
|
return null;
|
|
57
44
|
}
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
// to a mode and is stricter than the default, so "resolved at all" is the
|
|
61
|
-
// wrong question to ask about danger.
|
|
62
|
-
const unsafe = value
|
|
63
|
-
? ((_a = mode.unsafeValues) !== null && _a !== void 0 ? _a : []).indexOf(value) !== -1
|
|
64
|
-
: !!mode.menuLabel;
|
|
65
|
-
// Name the VALUE where there is one - three enum values sharing the mode's
|
|
66
|
-
// title render as one indistinguishable label.
|
|
45
|
+
// Carrying a menu label IS a boolean mode's declaration that it skips
|
|
46
|
+
// approval - it is what puts a variant in the menu.
|
|
67
47
|
return {
|
|
68
48
|
mode,
|
|
69
|
-
label: (
|
|
70
|
-
unsafe
|
|
49
|
+
label: (_a = mode.menuLabel) !== null && _a !== void 0 ? _a : mode.title,
|
|
50
|
+
unsafe: !!mode.menuLabel
|
|
71
51
|
};
|
|
72
52
|
}
|
package/lib/core/panel.d.ts
CHANGED
|
@@ -188,7 +188,7 @@ export declare class AssistantSessionsPanel extends Widget {
|
|
|
188
188
|
private _setRefreshSpinning;
|
|
189
189
|
private _setActiveRow;
|
|
190
190
|
private _cmd;
|
|
191
|
-
/**
|
|
191
|
+
/** Launch modes that produce a menu variant - the assistant's own
|
|
192
192
|
* skip-approval switch, under the assistant's own name. */
|
|
193
193
|
private get _variantModes();
|
|
194
194
|
/** The launch mode a PLAIN action resolves to right now, or null.
|
|
@@ -298,8 +298,6 @@ export declare class AssistantSessionsPanel extends Widget {
|
|
|
298
298
|
private _newSessionMenu;
|
|
299
299
|
/** Re-writes the `+` button's title. Set once the shell exists. */
|
|
300
300
|
private _renameNewButton;
|
|
301
|
-
/** Re-draws the `+` button's glyph. Set once the shell exists. */
|
|
302
|
-
private _repaintNewIcon;
|
|
303
301
|
private _lastBranches;
|
|
304
302
|
private _lastBranchesCurrent;
|
|
305
303
|
private _colouredTabs;
|
package/lib/core/panel.js
CHANGED
|
@@ -107,8 +107,6 @@ export class AssistantSessionsPanel extends Widget {
|
|
|
107
107
|
this._roving = {};
|
|
108
108
|
/** Re-writes the `+` button's title. Set once the shell exists. */
|
|
109
109
|
this._renameNewButton = null;
|
|
110
|
-
/** Re-draws the `+` button's glyph. Set once the shell exists. */
|
|
111
|
-
this._repaintNewIcon = null;
|
|
112
110
|
this._lastBranches = [];
|
|
113
111
|
this._lastBranchesCurrent = '';
|
|
114
112
|
this._colouredTabs = true;
|
|
@@ -220,14 +218,12 @@ export class AssistantSessionsPanel extends Widget {
|
|
|
220
218
|
/** Current values of this provider's launch modes, read from settings. Each
|
|
221
219
|
* key is an `ILaunchMode.id` in the assistant's own terminology. */
|
|
222
220
|
setModes(modes) {
|
|
223
|
-
var _a
|
|
221
|
+
var _a;
|
|
224
222
|
this._modes = { ...modes };
|
|
225
223
|
// Menu labels are lazy and re-read this on every open; the button's title
|
|
226
|
-
// is a written string, so it has to be rewritten here.
|
|
224
|
+
// is a written string, so it has to be rewritten here. The glyph needs no
|
|
225
|
+
// such hook - it is always "+", whatever mode is armed (DEF-112).
|
|
227
226
|
(_a = this._renameNewButton) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
228
|
-
// Same for its glyph - a menu item re-reads its icon on every open, a
|
|
229
|
-
// painted button does not.
|
|
230
|
-
(_b = this._repaintNewIcon) === null || _b === void 0 ? void 0 : _b.call(this);
|
|
231
227
|
}
|
|
232
228
|
setColouredTabs(on) {
|
|
233
229
|
this._colouredTabs = on;
|
|
@@ -282,25 +278,11 @@ export class AssistantSessionsPanel extends Widget {
|
|
|
282
278
|
// after turning an approval-free mode on (DEF-38).
|
|
283
279
|
this._renameNewButton = nameNewButton;
|
|
284
280
|
nameNewButton();
|
|
285
|
-
// The glyph
|
|
286
|
-
//
|
|
287
|
-
//
|
|
288
|
-
//
|
|
289
|
-
|
|
290
|
-
// wearing no warning at all.
|
|
291
|
-
const paintNewIcon = () => {
|
|
292
|
-
var _a;
|
|
293
|
-
const icon = (_a = (this._visibleVariantCount() === 0 ? this._variantIcon() : undefined)) !== null && _a !== void 0 ? _a : addIcon;
|
|
294
|
-
// `LabIcon.element` appends into the container, so the previous glyph
|
|
295
|
-
// has to go or the button would collect one svg per settings change.
|
|
296
|
-
newBtn.replaceChildren();
|
|
297
|
-
icon.element({ container: newBtn });
|
|
298
|
-
};
|
|
299
|
-
// Held for the same reason the title is: the shell is built before
|
|
300
|
-
// settings arrive, so what is drawn here can only say "no mode in force"
|
|
301
|
-
// and `setModes` has to repaint it (DEF-38).
|
|
302
|
-
this._repaintNewIcon = paintNewIcon;
|
|
303
|
-
paintNewIcon();
|
|
281
|
+
// The glyph is always "+", whatever mode is armed (DEF-112): the shield
|
|
282
|
+
// marks the menu ENTRIES that skip approval, while the button that offers
|
|
283
|
+
// or launches stays neutral - an armed mode is still named in the title
|
|
284
|
+
// above, so the launch never goes unnamed.
|
|
285
|
+
addIcon.element({ container: newBtn });
|
|
304
286
|
newBtn.addEventListener('click', () => {
|
|
305
287
|
// With a mode in force the variant items suppress themselves, leaving a
|
|
306
288
|
// dropdown with one entry - two clicks for its only outcome. Do it.
|
|
@@ -1637,10 +1619,10 @@ export class AssistantSessionsPanel extends Widget {
|
|
|
1637
1619
|
_cmd(action) {
|
|
1638
1620
|
return commandId(this._descriptor.id, action);
|
|
1639
1621
|
}
|
|
1640
|
-
/**
|
|
1622
|
+
/** Launch modes that produce a menu variant - the assistant's own
|
|
1641
1623
|
* skip-approval switch, under the assistant's own name. */
|
|
1642
1624
|
get _variantModes() {
|
|
1643
|
-
return this._descriptor.launchModes.filter(m =>
|
|
1625
|
+
return this._descriptor.launchModes.filter(m => !!m.menuLabel);
|
|
1644
1626
|
}
|
|
1645
1627
|
/** The launch mode a PLAIN action resolves to right now, or null.
|
|
1646
1628
|
*
|
package/lib/core/types.d.ts
CHANGED
|
@@ -19,9 +19,8 @@ export type ForkStrategy = 'native-flag' | 'native-command' | 'server-copy';
|
|
|
19
19
|
* the extension's own write-back store always wins over all three. */
|
|
20
20
|
export type ColourSource = 'native' | 'derived' | 'none';
|
|
21
21
|
/** One launch-behaviour setting of an assistant, in that assistant's own
|
|
22
|
-
* terminology.
|
|
23
|
-
*
|
|
24
|
-
* `enum` modes are settings-only choices passed through on every launch. */
|
|
22
|
+
* terminology. A launch mode is a boolean skip-approval switch: it gets a
|
|
23
|
+
* settings toggle (off by default) AND a context-menu launch variant. */
|
|
25
24
|
export interface ILaunchMode {
|
|
26
25
|
/** Settings key under `providers.<id>.` and launch-payload key. Uses the
|
|
27
26
|
* assistant's own terminology, never a normalised core name. */
|
|
@@ -30,24 +29,12 @@ export interface ILaunchMode {
|
|
|
30
29
|
title: string;
|
|
31
30
|
/** Settings description. */
|
|
32
31
|
description: string;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
values?: string[];
|
|
36
|
-
/** Default value. Boolean modes default to `false` without exception. */
|
|
37
|
-
default: boolean | string;
|
|
32
|
+
/** Default value - `false` without exception. */
|
|
33
|
+
default: boolean;
|
|
38
34
|
/** Menu label for the launch variant this mode produces, e.g.
|
|
39
|
-
* `Skip Permissions`.
|
|
35
|
+
* `Skip Permissions`. Carrying one IS the mode's declaration that it skips
|
|
36
|
+
* approval - it is what puts a variant in the menu. */
|
|
40
37
|
menuLabel?: string;
|
|
41
|
-
/** `enum` modes only: the values that WIDEN what the assistant may do
|
|
42
|
-
* without asking. The panel warns on these and names the value; every other
|
|
43
|
-
* value is a settings choice and is marked as one.
|
|
44
|
-
*
|
|
45
|
-
* Declared per provider rather than inferred, because "a mode resolved at
|
|
46
|
-
* all" is not the same question: Gemini's `plan` is read-only - stricter
|
|
47
|
-
* than the default - and marking it the same as `yolo` says nothing about
|
|
48
|
-
* either. A boolean mode needs no entry here; carrying a `menuLabel` is
|
|
49
|
-
* already its declaration that it skips approval. */
|
|
50
|
-
unsafeValues?: string[];
|
|
51
38
|
}
|
|
52
39
|
/** Everything the core needs to know about one assistant. Pure data - no
|
|
53
40
|
* JupyterLab imports - so the settings-schema generator can read it under
|
package/lib/providers/claude.js
CHANGED
|
@@ -52,7 +52,6 @@ export const descriptor = {
|
|
|
52
52
|
id: 'dangerouslySkipPermissions',
|
|
53
53
|
title: 'Dangerously skip permissions',
|
|
54
54
|
description: 'When enabled, newly spawned and resumed sessions are launched with `--dangerously-skip-permissions`. Bypasses every Claude Code permission prompt - only enable in sandboxes you trust.',
|
|
55
|
-
kind: 'boolean',
|
|
56
55
|
default: false,
|
|
57
56
|
menuLabel: 'Skip Permissions'
|
|
58
57
|
}
|
package/lib/providers/codex.js
CHANGED
|
@@ -48,7 +48,6 @@ export const descriptor = {
|
|
|
48
48
|
id: BYPASS_MODE,
|
|
49
49
|
title: 'Bypass Codex approvals and sandbox',
|
|
50
50
|
description: 'When enabled, newly spawned and resumed sessions are launched with `--dangerously-bypass-approvals-and-sandbox`. Bypasses every Codex approval prompt and sandbox - only enable in environments you trust.',
|
|
51
|
-
kind: 'boolean',
|
|
52
51
|
default: false,
|
|
53
52
|
menuLabel: 'Bypass Approvals'
|
|
54
53
|
}
|
package/lib/providers/gemini.js
CHANGED
|
@@ -28,11 +28,10 @@
|
|
|
28
28
|
const geminiSvgStr = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 65 65" width="16" height="16">
|
|
29
29
|
<path class="jp-icon3" fill="#616161" d="M32.447 0c.68 0 1.273.465 1.439 1.125a38.904 38.904 0 001.999 5.905c2.152 5 5.105 9.376 8.854 13.125 3.751 3.75 8.126 6.703 13.125 8.855a38.98 38.98 0 005.906 1.999c.66.166 1.124.758 1.124 1.438 0 .68-.464 1.273-1.125 1.439a38.902 38.902 0 00-5.905 1.999c-5 2.152-9.375 5.105-13.125 8.854-3.749 3.751-6.702 8.126-8.854 13.125a38.973 38.973 0 00-2 5.906 1.485 1.485 0 01-1.438 1.124c-.68 0-1.272-.464-1.438-1.125a38.913 38.913 0 00-2-5.905c-2.151-5-5.103-9.375-8.854-13.125-3.75-3.749-8.125-6.702-13.125-8.854a38.973 38.973 0 00-5.905-2A1.485 1.485 0 010 32.448c0-.68.465-1.272 1.125-1.438a38.903 38.903 0 005.905-2c5-2.151 9.376-5.104 13.125-8.854 3.75-3.749 6.703-8.125 8.855-13.125a38.972 38.972 0 001.999-5.905A1.485 1.485 0 0132.447 0z"/>
|
|
30
30
|
</svg>`;
|
|
31
|
-
// Gemini's own
|
|
32
|
-
// terminology rather than normalised, because
|
|
31
|
+
// Gemini's own name for its approval switch. Kept in the assistant's
|
|
32
|
+
// terminology rather than normalised, because it is both the settings key
|
|
33
33
|
// under `providers.gemini.` and the mode token the server maps to a CLI flag.
|
|
34
34
|
const YOLO_MODE = 'yoloMode';
|
|
35
|
-
const APPROVAL_MODE = 'approvalMode';
|
|
36
35
|
export const descriptor = {
|
|
37
36
|
id: 'gemini',
|
|
38
37
|
label: 'Gemini',
|
|
@@ -54,19 +53,8 @@ export const descriptor = {
|
|
|
54
53
|
id: YOLO_MODE,
|
|
55
54
|
title: 'YOLO mode',
|
|
56
55
|
description: 'When enabled, newly spawned and resumed sessions are launched with `--yolo`. Gemini auto-approves every tool call without asking - only enable in workspaces you trust.',
|
|
57
|
-
kind: 'boolean',
|
|
58
56
|
default: false,
|
|
59
57
|
menuLabel: 'YOLO'
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
id: APPROVAL_MODE,
|
|
63
|
-
title: 'Approval mode',
|
|
64
|
-
description: 'Approval ladder passed as `--approval-mode` when set to a value other than the default. A non-default value here takes precedence over the YOLO switch; only the forced YOLO menu action overrides it. `default` prompts for approval, `auto_edit` auto-approves edit tools, `yolo` auto-approves every tool, `plan` is read-only.',
|
|
65
|
-
kind: 'enum',
|
|
66
|
-
values: ['default', 'auto_edit', 'yolo', 'plan'],
|
|
67
|
-
default: 'default',
|
|
68
|
-
// `plan` is read-only and `default` prompts, so neither widens anything.
|
|
69
|
-
unsafeValues: ['auto_edit', 'yolo']
|
|
70
58
|
}
|
|
71
59
|
],
|
|
72
60
|
hasRemoteControl: false,
|
package/lib/providers/kimi.js
CHANGED
|
@@ -122,7 +122,6 @@ export const descriptor = {
|
|
|
122
122
|
id: 'yoloMode',
|
|
123
123
|
title: 'YOLO mode',
|
|
124
124
|
description: 'When enabled, newly spawned and resumed sessions are launched with `--yolo`. Kimi auto-approves regular tool calls without asking - only enable in workspaces you trust.',
|
|
125
|
-
kind: 'boolean',
|
|
126
125
|
default: false,
|
|
127
126
|
menuLabel: 'YOLO'
|
|
128
127
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jupyterlab_ai_code_assistants_extension",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.23",
|
|
4
4
|
"description": "Jupyterlab extension to replace individual jupyterlab_*_code_extension and integrate into one, that offers joint capability, joint settings page and individual right toolbar panels per code assistant, with the ability in settings to decide which code assistant support is on (default - all are enabled)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jupyter",
|
package/schema/plugin.json
CHANGED
|
@@ -69,13 +69,6 @@
|
|
|
69
69
|
"description": "When enabled, newly spawned and resumed sessions are launched with `--yolo`. Gemini auto-approves every tool call without asking - only enable in workspaces you trust.",
|
|
70
70
|
"default": false
|
|
71
71
|
},
|
|
72
|
-
"providers.gemini.approvalMode": {
|
|
73
|
-
"type": "string",
|
|
74
|
-
"title": "Gemini: Approval mode",
|
|
75
|
-
"description": "Approval ladder passed as `--approval-mode` when set to a value other than the default. A non-default value here takes precedence over the YOLO switch; only the forced YOLO menu action overrides it. `default` prompts for approval, `auto_edit` auto-approves edit tools, `yolo` auto-approves every tool, `plan` is read-only.",
|
|
76
|
-
"default": "default",
|
|
77
|
-
"enum": ["default", "auto_edit", "yolo", "plan"]
|
|
78
|
-
},
|
|
79
72
|
"providers.kimi.enabled": {
|
|
80
73
|
"type": "boolean",
|
|
81
74
|
"title": "Kimi: enabled",
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Launch-mode
|
|
2
|
+
* Launch-mode resolution.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Every mode is a boolean skip-approval switch in the assistant's own
|
|
5
|
+
* terminology (DEF-111 retired the one enum ladder, Gemini's `approvalMode`),
|
|
6
|
+
* and the payload carries only one token: `force` wins outright, otherwise
|
|
7
|
+
* the first switch that is on fires.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { resolveLaunchMode, resolvedLaunchModeEntry } from '../core/modes';
|
|
@@ -15,44 +15,33 @@ const MODES: ILaunchMode[] = [
|
|
|
15
15
|
id: 'yoloMode',
|
|
16
16
|
title: 'YOLO',
|
|
17
17
|
description: 'Boolean switch.',
|
|
18
|
-
kind: 'boolean',
|
|
19
18
|
default: false,
|
|
20
19
|
// Carrying a menu label IS a boolean mode's declaration that it skips
|
|
21
20
|
// approval - it is what puts a variant in the menu.
|
|
22
21
|
menuLabel: 'YOLO'
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
id: 'approvalMode',
|
|
26
|
-
title: 'Approval',
|
|
27
|
-
description: 'Enum ladder.',
|
|
28
|
-
kind: 'enum',
|
|
29
|
-
values: ['default', 'plan', 'yolo'],
|
|
30
|
-
default: 'default',
|
|
31
|
-
unsafeValues: ['yolo']
|
|
32
22
|
}
|
|
33
23
|
];
|
|
34
24
|
|
|
35
25
|
describe('resolveLaunchMode', () => {
|
|
36
|
-
it('
|
|
37
|
-
expect(
|
|
38
|
-
resolveLaunchMode(MODES, { yoloMode: true, approvalMode: 'plan' })
|
|
39
|
-
).toEqual('approvalMode=plan');
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('sends the boolean while every enum sits at its default', () => {
|
|
43
|
-
expect(
|
|
44
|
-
resolveLaunchMode(MODES, { yoloMode: true, approvalMode: 'default' })
|
|
45
|
-
).toEqual('yoloMode');
|
|
26
|
+
it('sends the boolean that is on', () => {
|
|
27
|
+
expect(resolveLaunchMode(MODES, { yoloMode: true })).toEqual('yoloMode');
|
|
46
28
|
});
|
|
47
29
|
|
|
48
30
|
it('sends nothing when no mode is set', () => {
|
|
49
31
|
expect(resolveLaunchMode(MODES, {})).toBeUndefined();
|
|
32
|
+
expect(resolveLaunchMode(MODES, { yoloMode: false })).toBeUndefined();
|
|
50
33
|
});
|
|
51
34
|
|
|
52
35
|
it('forces the requested mode whatever the settings say', () => {
|
|
36
|
+
expect(resolveLaunchMode(MODES, {}, 'yoloMode')).toEqual('yoloMode');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('ignores a token from a retired setting', () => {
|
|
40
|
+
// A stale `approvalMode` value in saved settings is not a boolean that is
|
|
41
|
+
// on - it must never become a launch token (DEF-111).
|
|
53
42
|
expect(
|
|
54
|
-
resolveLaunchMode(MODES, { approvalMode: 'plan' }
|
|
55
|
-
).
|
|
43
|
+
resolveLaunchMode(MODES, { approvalMode: 'plan' } as any)
|
|
44
|
+
).toBeUndefined();
|
|
56
45
|
});
|
|
57
46
|
});
|
|
58
47
|
|
|
@@ -60,8 +49,7 @@ describe('resolvedLaunchModeEntry', () => {
|
|
|
60
49
|
// What the panel marks its PLAIN menu items from. Deciding the warning glyph
|
|
61
50
|
// from the menu's `force` argument instead leaves the entry the user
|
|
62
51
|
// actually clicks unmarked, while marking a forced duplicate that builds the
|
|
63
|
-
// identical launch.
|
|
64
|
-
// error one level down: it warns on Gemini's `plan`, which is read-only.
|
|
52
|
+
// identical launch.
|
|
65
53
|
it('warns on a boolean skip-approval switch and names it', () => {
|
|
66
54
|
const r = resolvedLaunchModeEntry(MODES, { yoloMode: true });
|
|
67
55
|
expect(r?.mode.id).toEqual('yoloMode');
|
|
@@ -69,32 +57,8 @@ describe('resolvedLaunchModeEntry', () => {
|
|
|
69
57
|
expect(r?.unsafe).toBe(true);
|
|
70
58
|
});
|
|
71
59
|
|
|
72
|
-
it('warns on an enum value the provider declared as widening', () => {
|
|
73
|
-
const r = resolvedLaunchModeEntry(MODES, { approvalMode: 'yolo' });
|
|
74
|
-
expect(r?.mode.id).toEqual('approvalMode');
|
|
75
|
-
expect(r?.label).toEqual('yolo');
|
|
76
|
-
expect(r?.unsafe).toBe(true);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('does NOT warn on an enum value that is stricter than the default', () => {
|
|
80
|
-
// `plan` is read-only. Marking it like `yolo` says nothing about either.
|
|
81
|
-
const r = resolvedLaunchModeEntry(MODES, { approvalMode: 'plan' });
|
|
82
|
-
expect(r?.mode.id).toEqual('approvalMode');
|
|
83
|
-
expect(r?.label).toEqual('plan');
|
|
84
|
-
expect(r?.unsafe).toBe(false);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('names the mode that actually wins, not both', () => {
|
|
88
|
-
expect(
|
|
89
|
-
resolvedLaunchModeEntry(MODES, { yoloMode: true, approvalMode: 'plan' })
|
|
90
|
-
?.mode.id
|
|
91
|
-
).toEqual('approvalMode');
|
|
92
|
-
});
|
|
93
|
-
|
|
94
60
|
it('names nothing for a launch that carries no mode', () => {
|
|
95
61
|
expect(resolvedLaunchModeEntry(MODES, {})).toBeNull();
|
|
96
|
-
expect(
|
|
97
|
-
resolvedLaunchModeEntry(MODES, { approvalMode: 'default' })
|
|
98
|
-
).toBeNull();
|
|
62
|
+
expect(resolvedLaunchModeEntry(MODES, { yoloMode: false })).toBeNull();
|
|
99
63
|
});
|
|
100
64
|
});
|
|
@@ -66,7 +66,6 @@ const DESCRIPTOR: IProviderDescriptor = {
|
|
|
66
66
|
id: 'skip',
|
|
67
67
|
title: 'Skip approvals',
|
|
68
68
|
description: 'Run without asking.',
|
|
69
|
-
kind: 'boolean',
|
|
70
69
|
default: false,
|
|
71
70
|
menuLabel: 'Skip Permissions'
|
|
72
71
|
}
|
|
@@ -277,16 +276,14 @@ describe('the + button names and marks the launch it performs', () => {
|
|
|
277
276
|
expect(newBtn().title).not.toContain('(Skip Permissions)');
|
|
278
277
|
});
|
|
279
278
|
|
|
280
|
-
it('DEF-
|
|
281
|
-
//
|
|
282
|
-
//
|
|
283
|
-
//
|
|
279
|
+
it('DEF-112 - the glyph is always +, one svg at a time', () => {
|
|
280
|
+
// The shield marks the menu entries that skip approval; the button that
|
|
281
|
+
// offers or launches stays neutral in every mode state. The mode is still
|
|
282
|
+
// named in the title, per DEF-36 above.
|
|
284
283
|
expect(glyphs()).toEqual([addIcon.name]);
|
|
285
284
|
panel.setModes({ skip: true });
|
|
286
285
|
expect((panel as any)._visibleVariantCount()).toEqual(0);
|
|
287
|
-
expect(glyphs()).toEqual([
|
|
288
|
-
// `LabIcon.element` appends, so a button that is not cleared collects one
|
|
289
|
-
// svg per settings change.
|
|
286
|
+
expect(glyphs()).toEqual([addIcon.name]);
|
|
290
287
|
panel.setModes({ skip: false });
|
|
291
288
|
expect(glyphs()).toEqual([addIcon.name]);
|
|
292
289
|
});
|
|
@@ -79,13 +79,8 @@ describe('the providers barrel', () => {
|
|
|
79
79
|
expect(mode.id.trim()).toBeTruthy();
|
|
80
80
|
expect(mode.title.trim()).toBeTruthy();
|
|
81
81
|
expect(mode.description.trim()).toBeTruthy();
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
expect(mode.default).toBe(false);
|
|
85
|
-
} else {
|
|
86
|
-
expect(mode.values).toBeDefined();
|
|
87
|
-
expect(mode.values).toContain(mode.default as string);
|
|
88
|
-
}
|
|
82
|
+
// Every unsafe switch is off by default, without exception.
|
|
83
|
+
expect(mode.default).toBe(false);
|
|
89
84
|
}
|
|
90
85
|
const ids = descriptor.launchModes.map(m => m.id);
|
|
91
86
|
expect(new Set(ids).size).toEqual(ids.length);
|
package/src/core/modes.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
// Launch-mode resolution: which single mode token, if any, one launch carries.
|
|
2
2
|
//
|
|
3
3
|
// Its own module because the panel is the only caller but not the only reader -
|
|
4
|
-
// the
|
|
5
|
-
//
|
|
4
|
+
// the rule that one launch carries at most one mode is worth asserting on its
|
|
5
|
+
// own, and this file pulls in no JupyterLab surface.
|
|
6
6
|
|
|
7
7
|
import { ILaunchMode } from './types';
|
|
8
8
|
|
|
9
9
|
/** A resolved launch mode, with what to call it and whether to warn. */
|
|
10
10
|
export interface IResolvedLaunchMode {
|
|
11
11
|
mode: ILaunchMode;
|
|
12
|
-
/** What the menu should call it - the
|
|
12
|
+
/** What the menu should call it - the mode's own label. */
|
|
13
13
|
label: string;
|
|
14
14
|
/** Whether this widens what the assistant may do without asking. */
|
|
15
15
|
unsafe: boolean;
|
|
@@ -20,11 +20,8 @@ export interface IResolvedLaunchMode {
|
|
|
20
20
|
*
|
|
21
21
|
* The payload carries at most one mode, because the server maps one token to
|
|
22
22
|
* one flag. `force` wins outright - that is what the menu's variant entries
|
|
23
|
-
* do. Otherwise
|
|
24
|
-
*
|
|
25
|
-
* left on must not silently invert it. A boolean fires only while every enum
|
|
26
|
-
* mode sits at its default. An enum at its default sends nothing - it is what
|
|
27
|
-
* the CLI would do unasked.
|
|
23
|
+
* do. Otherwise the first switch that is on fires. Every mode is a boolean
|
|
24
|
+
* skip-approval switch, so "on" always means the same thing.
|
|
28
25
|
*/
|
|
29
26
|
export function resolveLaunchMode(
|
|
30
27
|
launchModes: ILaunchMode[],
|
|
@@ -35,18 +32,7 @@ export function resolveLaunchMode(
|
|
|
35
32
|
return force;
|
|
36
33
|
}
|
|
37
34
|
for (const mode of launchModes) {
|
|
38
|
-
|
|
39
|
-
if (
|
|
40
|
-
mode.kind !== 'boolean' &&
|
|
41
|
-
typeof value === 'string' &&
|
|
42
|
-
value &&
|
|
43
|
-
value !== mode.default
|
|
44
|
-
) {
|
|
45
|
-
return `${mode.id}=${value}`;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
for (const mode of launchModes) {
|
|
49
|
-
if (mode.kind === 'boolean' && values[mode.id] === true) {
|
|
35
|
+
if (values[mode.id] === true) {
|
|
50
36
|
return mode.id;
|
|
51
37
|
}
|
|
52
38
|
}
|
|
@@ -71,23 +57,15 @@ export function resolvedLaunchModeEntry(
|
|
|
71
57
|
if (!token) {
|
|
72
58
|
return null;
|
|
73
59
|
}
|
|
74
|
-
const
|
|
75
|
-
const mode = launchModes.find(m => m.id === id);
|
|
60
|
+
const mode = launchModes.find(m => m.id === token);
|
|
76
61
|
if (!mode) {
|
|
77
62
|
return null;
|
|
78
63
|
}
|
|
79
|
-
//
|
|
80
|
-
//
|
|
81
|
-
// to a mode and is stricter than the default, so "resolved at all" is the
|
|
82
|
-
// wrong question to ask about danger.
|
|
83
|
-
const unsafe = value
|
|
84
|
-
? (mode.unsafeValues ?? []).indexOf(value) !== -1
|
|
85
|
-
: !!mode.menuLabel;
|
|
86
|
-
// Name the VALUE where there is one - three enum values sharing the mode's
|
|
87
|
-
// title render as one indistinguishable label.
|
|
64
|
+
// Carrying a menu label IS a boolean mode's declaration that it skips
|
|
65
|
+
// approval - it is what puts a variant in the menu.
|
|
88
66
|
return {
|
|
89
67
|
mode,
|
|
90
|
-
label:
|
|
91
|
-
unsafe
|
|
68
|
+
label: mode.menuLabel ?? mode.title,
|
|
69
|
+
unsafe: !!mode.menuLabel
|
|
92
70
|
};
|
|
93
71
|
}
|
package/src/core/panel.ts
CHANGED
|
@@ -276,11 +276,9 @@ export class AssistantSessionsPanel extends Widget {
|
|
|
276
276
|
setModes(modes: Record<string, boolean | string>): void {
|
|
277
277
|
this._modes = { ...modes };
|
|
278
278
|
// Menu labels are lazy and re-read this on every open; the button's title
|
|
279
|
-
// is a written string, so it has to be rewritten here.
|
|
279
|
+
// is a written string, so it has to be rewritten here. The glyph needs no
|
|
280
|
+
// such hook - it is always "+", whatever mode is armed (DEF-112).
|
|
280
281
|
this._renameNewButton?.();
|
|
281
|
-
// Same for its glyph - a menu item re-reads its icon on every open, a
|
|
282
|
-
// painted button does not.
|
|
283
|
-
this._repaintNewIcon?.();
|
|
284
282
|
}
|
|
285
283
|
|
|
286
284
|
setColouredTabs(on: boolean): void {
|
|
@@ -344,26 +342,11 @@ export class AssistantSessionsPanel extends Widget {
|
|
|
344
342
|
// after turning an approval-free mode on (DEF-38).
|
|
345
343
|
this._renameNewButton = nameNewButton;
|
|
346
344
|
nameNewButton();
|
|
347
|
-
// The glyph
|
|
348
|
-
//
|
|
349
|
-
//
|
|
350
|
-
//
|
|
351
|
-
|
|
352
|
-
// wearing no warning at all.
|
|
353
|
-
const paintNewIcon = (): void => {
|
|
354
|
-
const icon =
|
|
355
|
-
(this._visibleVariantCount() === 0 ? this._variantIcon() : undefined) ??
|
|
356
|
-
addIcon;
|
|
357
|
-
// `LabIcon.element` appends into the container, so the previous glyph
|
|
358
|
-
// has to go or the button would collect one svg per settings change.
|
|
359
|
-
newBtn.replaceChildren();
|
|
360
|
-
icon.element({ container: newBtn });
|
|
361
|
-
};
|
|
362
|
-
// Held for the same reason the title is: the shell is built before
|
|
363
|
-
// settings arrive, so what is drawn here can only say "no mode in force"
|
|
364
|
-
// and `setModes` has to repaint it (DEF-38).
|
|
365
|
-
this._repaintNewIcon = paintNewIcon;
|
|
366
|
-
paintNewIcon();
|
|
345
|
+
// The glyph is always "+", whatever mode is armed (DEF-112): the shield
|
|
346
|
+
// marks the menu ENTRIES that skip approval, while the button that offers
|
|
347
|
+
// or launches stays neutral - an armed mode is still named in the title
|
|
348
|
+
// above, so the launch never goes unnamed.
|
|
349
|
+
addIcon.element({ container: newBtn });
|
|
367
350
|
newBtn.addEventListener('click', () => {
|
|
368
351
|
// With a mode in force the variant items suppress themselves, leaving a
|
|
369
352
|
// dropdown with one entry - two clicks for its only outcome. Do it.
|
|
@@ -1928,12 +1911,10 @@ export class AssistantSessionsPanel extends Widget {
|
|
|
1928
1911
|
return commandId(this._descriptor.id, action);
|
|
1929
1912
|
}
|
|
1930
1913
|
|
|
1931
|
-
/**
|
|
1914
|
+
/** Launch modes that produce a menu variant - the assistant's own
|
|
1932
1915
|
* skip-approval switch, under the assistant's own name. */
|
|
1933
1916
|
private get _variantModes(): ILaunchMode[] {
|
|
1934
|
-
return this._descriptor.launchModes.filter(
|
|
1935
|
-
m => m.kind === 'boolean' && !!m.menuLabel
|
|
1936
|
-
);
|
|
1917
|
+
return this._descriptor.launchModes.filter(m => !!m.menuLabel);
|
|
1937
1918
|
}
|
|
1938
1919
|
|
|
1939
1920
|
/** The launch mode a PLAIN action resolves to right now, or null.
|
|
@@ -2656,8 +2637,6 @@ export class AssistantSessionsPanel extends Widget {
|
|
|
2656
2637
|
private _newSessionMenu!: Menu;
|
|
2657
2638
|
/** Re-writes the `+` button's title. Set once the shell exists. */
|
|
2658
2639
|
private _renameNewButton: (() => void) | null = null;
|
|
2659
|
-
/** Re-draws the `+` button's glyph. Set once the shell exists. */
|
|
2660
|
-
private _repaintNewIcon: (() => void) | null = null;
|
|
2661
2640
|
private _lastBranches: IBranch[] = [];
|
|
2662
2641
|
private _lastBranchesCurrent = '';
|
|
2663
2642
|
private _colouredTabs = true;
|
package/src/core/types.ts
CHANGED
|
@@ -27,9 +27,8 @@ export type ForkStrategy = 'native-flag' | 'native-command' | 'server-copy';
|
|
|
27
27
|
export type ColourSource = 'native' | 'derived' | 'none';
|
|
28
28
|
|
|
29
29
|
/** One launch-behaviour setting of an assistant, in that assistant's own
|
|
30
|
-
* terminology.
|
|
31
|
-
*
|
|
32
|
-
* `enum` modes are settings-only choices passed through on every launch. */
|
|
30
|
+
* terminology. A launch mode is a boolean skip-approval switch: it gets a
|
|
31
|
+
* settings toggle (off by default) AND a context-menu launch variant. */
|
|
33
32
|
export interface ILaunchMode {
|
|
34
33
|
/** Settings key under `providers.<id>.` and launch-payload key. Uses the
|
|
35
34
|
* assistant's own terminology, never a normalised core name. */
|
|
@@ -38,24 +37,12 @@ export interface ILaunchMode {
|
|
|
38
37
|
title: string;
|
|
39
38
|
/** Settings description. */
|
|
40
39
|
description: string;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
values?: string[];
|
|
44
|
-
/** Default value. Boolean modes default to `false` without exception. */
|
|
45
|
-
default: boolean | string;
|
|
40
|
+
/** Default value - `false` without exception. */
|
|
41
|
+
default: boolean;
|
|
46
42
|
/** Menu label for the launch variant this mode produces, e.g.
|
|
47
|
-
* `Skip Permissions`.
|
|
43
|
+
* `Skip Permissions`. Carrying one IS the mode's declaration that it skips
|
|
44
|
+
* approval - it is what puts a variant in the menu. */
|
|
48
45
|
menuLabel?: string;
|
|
49
|
-
/** `enum` modes only: the values that WIDEN what the assistant may do
|
|
50
|
-
* without asking. The panel warns on these and names the value; every other
|
|
51
|
-
* value is a settings choice and is marked as one.
|
|
52
|
-
*
|
|
53
|
-
* Declared per provider rather than inferred, because "a mode resolved at
|
|
54
|
-
* all" is not the same question: Gemini's `plan` is read-only - stricter
|
|
55
|
-
* than the default - and marking it the same as `yolo` says nothing about
|
|
56
|
-
* either. A boolean mode needs no entry here; carrying a `menuLabel` is
|
|
57
|
-
* already its declaration that it skips approval. */
|
|
58
|
-
unsafeValues?: string[];
|
|
59
46
|
}
|
|
60
47
|
|
|
61
48
|
/** Everything the core needs to know about one assistant. Pure data - no
|
package/src/providers/claude.ts
CHANGED
|
@@ -57,7 +57,6 @@ export const descriptor: IProviderDescriptor = {
|
|
|
57
57
|
title: 'Dangerously skip permissions',
|
|
58
58
|
description:
|
|
59
59
|
'When enabled, newly spawned and resumed sessions are launched with `--dangerously-skip-permissions`. Bypasses every Claude Code permission prompt - only enable in sandboxes you trust.',
|
|
60
|
-
kind: 'boolean',
|
|
61
60
|
default: false,
|
|
62
61
|
menuLabel: 'Skip Permissions'
|
|
63
62
|
}
|
package/src/providers/codex.ts
CHANGED
|
@@ -54,7 +54,6 @@ export const descriptor: IProviderDescriptor = {
|
|
|
54
54
|
title: 'Bypass Codex approvals and sandbox',
|
|
55
55
|
description:
|
|
56
56
|
'When enabled, newly spawned and resumed sessions are launched with `--dangerously-bypass-approvals-and-sandbox`. Bypasses every Codex approval prompt and sandbox - only enable in environments you trust.',
|
|
57
|
-
kind: 'boolean',
|
|
58
57
|
default: false,
|
|
59
58
|
menuLabel: 'Bypass Approvals'
|
|
60
59
|
}
|
package/src/providers/gemini.ts
CHANGED
|
@@ -32,11 +32,10 @@ const geminiSvgStr = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 65 65
|
|
|
32
32
|
<path class="jp-icon3" fill="#616161" d="M32.447 0c.68 0 1.273.465 1.439 1.125a38.904 38.904 0 001.999 5.905c2.152 5 5.105 9.376 8.854 13.125 3.751 3.75 8.126 6.703 13.125 8.855a38.98 38.98 0 005.906 1.999c.66.166 1.124.758 1.124 1.438 0 .68-.464 1.273-1.125 1.439a38.902 38.902 0 00-5.905 1.999c-5 2.152-9.375 5.105-13.125 8.854-3.749 3.751-6.702 8.126-8.854 13.125a38.973 38.973 0 00-2 5.906 1.485 1.485 0 01-1.438 1.124c-.68 0-1.272-.464-1.438-1.125a38.913 38.913 0 00-2-5.905c-2.151-5-5.103-9.375-8.854-13.125-3.75-3.749-8.125-6.702-13.125-8.854a38.973 38.973 0 00-5.905-2A1.485 1.485 0 010 32.448c0-.68.465-1.272 1.125-1.438a38.903 38.903 0 005.905-2c5-2.151 9.376-5.104 13.125-8.854 3.75-3.749 6.703-8.125 8.855-13.125a38.972 38.972 0 001.999-5.905A1.485 1.485 0 0132.447 0z"/>
|
|
33
33
|
</svg>`;
|
|
34
34
|
|
|
35
|
-
// Gemini's own
|
|
36
|
-
// terminology rather than normalised, because
|
|
35
|
+
// Gemini's own name for its approval switch. Kept in the assistant's
|
|
36
|
+
// terminology rather than normalised, because it is both the settings key
|
|
37
37
|
// under `providers.gemini.` and the mode token the server maps to a CLI flag.
|
|
38
38
|
const YOLO_MODE = 'yoloMode';
|
|
39
|
-
const APPROVAL_MODE = 'approvalMode';
|
|
40
39
|
|
|
41
40
|
export const descriptor: IProviderDescriptor = {
|
|
42
41
|
id: 'gemini',
|
|
@@ -60,20 +59,8 @@ export const descriptor: IProviderDescriptor = {
|
|
|
60
59
|
title: 'YOLO mode',
|
|
61
60
|
description:
|
|
62
61
|
'When enabled, newly spawned and resumed sessions are launched with `--yolo`. Gemini auto-approves every tool call without asking - only enable in workspaces you trust.',
|
|
63
|
-
kind: 'boolean',
|
|
64
62
|
default: false,
|
|
65
63
|
menuLabel: 'YOLO'
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
id: APPROVAL_MODE,
|
|
69
|
-
title: 'Approval mode',
|
|
70
|
-
description:
|
|
71
|
-
'Approval ladder passed as `--approval-mode` when set to a value other than the default. A non-default value here takes precedence over the YOLO switch; only the forced YOLO menu action overrides it. `default` prompts for approval, `auto_edit` auto-approves edit tools, `yolo` auto-approves every tool, `plan` is read-only.',
|
|
72
|
-
kind: 'enum',
|
|
73
|
-
values: ['default', 'auto_edit', 'yolo', 'plan'],
|
|
74
|
-
default: 'default',
|
|
75
|
-
// `plan` is read-only and `default` prompts, so neither widens anything.
|
|
76
|
-
unsafeValues: ['auto_edit', 'yolo']
|
|
77
64
|
}
|
|
78
65
|
],
|
|
79
66
|
hasRemoteControl: false,
|
package/src/providers/kimi.ts
CHANGED
|
@@ -135,7 +135,6 @@ export const descriptor: IProviderDescriptor = {
|
|
|
135
135
|
title: 'YOLO mode',
|
|
136
136
|
description:
|
|
137
137
|
'When enabled, newly spawned and resumed sessions are launched with `--yolo`. Kimi auto-approves regular tool calls without asking - only enable in workspaces you trust.',
|
|
138
|
-
kind: 'boolean',
|
|
139
138
|
default: false,
|
|
140
139
|
menuLabel: 'YOLO'
|
|
141
140
|
}
|