xtralab 0.11.0 → 0.11.1

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 CHANGED
@@ -210,8 +210,10 @@ Edit the `agents` array:
210
210
  // Hide an agent
211
211
  { "id": "kiro", "enabled": false },
212
212
 
213
- // Override an agent's command (e.g. point Claude at a shell alias)
214
- { "id": "claude", "command": "cl", "requireAvailable": false },
213
+ // Override an agent's command, e.g. point Claude at a shell alias.
214
+ // Changing the command keeps the card visible even when the alias is
215
+ // not on PATH, so requireAvailable: false is no longer needed here.
216
+ { "id": "claude", "command": "cl" },
215
217
 
216
218
  // Add a new agent; promptArgs: [] appends the prompt as a positional arg
217
219
  { "id": "aider", "label": "Aider", "command": "aider", "promptArgs": [] }
@@ -59,7 +59,12 @@ export interface IAgentSettings {
59
59
  * palette. Defaults to true.
60
60
  */
61
61
  enabled?: boolean;
62
- /** See `IAgent.requireAvailable`. */
62
+ /**
63
+ * See `IAgent.requireAvailable`. Defaults to true for a built-in agent that
64
+ * still uses its shipped command, and to false once you override the
65
+ * `command` (a user-chosen command — often a shell alias — is trusted and
66
+ * always shown). Set it explicitly to force the check on or off.
67
+ */
63
68
  requireAvailable?: boolean;
64
69
  /**
65
70
  * See `IAgent.promptArgs`. Pass an empty array to mark the agent as
@@ -81,5 +86,10 @@ export declare function defaultAgentSettings(): IAgentSettings[];
81
86
  * their built-in fields unless explicitly overridden; user-only entries are
82
87
  * appended. `enabled: false` filters an entry out of the result entirely
83
88
  * (so callers don't need to check the flag again).
89
+ *
90
+ * Overriding a built-in agent's `command` also turns its `requireAvailable`
91
+ * off, so the card survives the launcher's `which`-based availability filter
92
+ * even when the new command is a shell alias the server can't resolve. See the
93
+ * built-in branch below for the rationale.
84
94
  */
85
95
  export declare function mergeAgents(overrides: IAgentSettings[]): IAgent[];
@@ -139,6 +139,11 @@ function resolveIcon(id, iconSvg) {
139
139
  * their built-in fields unless explicitly overridden; user-only entries are
140
140
  * appended. `enabled: false` filters an entry out of the result entirely
141
141
  * (so callers don't need to check the flag again).
142
+ *
143
+ * Overriding a built-in agent's `command` also turns its `requireAvailable`
144
+ * off, so the card survives the launcher's `which`-based availability filter
145
+ * even when the new command is a shell alias the server can't resolve. See the
146
+ * built-in branch below for the rationale.
142
147
  */
143
148
  export function mergeAgents(overrides) {
144
149
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
@@ -154,16 +159,30 @@ export function mergeAgents(overrides) {
154
159
  if (override.enabled === false) {
155
160
  continue;
156
161
  }
162
+ const command = (_a = override.command) !== null && _a !== void 0 ? _a : base.command;
157
163
  merged.push({
158
164
  id: base.id,
159
- label: (_a = override.label) !== null && _a !== void 0 ? _a : base.label,
160
- caption: (_b = override.caption) !== null && _b !== void 0 ? _b : base.caption,
161
- command: (_c = override.command) !== null && _c !== void 0 ? _c : base.command,
165
+ label: (_b = override.label) !== null && _b !== void 0 ? _b : base.label,
166
+ caption: (_c = override.caption) !== null && _c !== void 0 ? _c : base.caption,
167
+ command,
162
168
  icon: override.iconSvg
163
169
  ? resolveIcon(base.id, override.iconSvg)
164
170
  : base.icon,
165
171
  rank: (_d = override.rank) !== null && _d !== void 0 ? _d : base.rank,
166
- requireAvailable: (_e = override.requireAvailable) !== null && _e !== void 0 ? _e : base.requireAvailable,
172
+ // The availability filter exists to prune xtralab's *built-in* command
173
+ // from the launcher when it isn't installed. Once the user points the
174
+ // agent at their own command — e.g. the `ccm` alias wrapping `claude
175
+ // --effort=max …` — the server's `shutil.which` probe can't see it
176
+ // (aliases and shell functions only exist inside an interactive shell),
177
+ // so keeping the check on would wrongly hide the card. We therefore only
178
+ // require availability while the command is still xtralab's default; a
179
+ // user-chosen command is trusted and always shown. An explicit
180
+ // `requireAvailable` still applies to the unchanged default command, so a
181
+ // user can alias `claude` itself and set `requireAvailable: false` (or
182
+ // force the check back on).
183
+ requireAvailable: command === base.command
184
+ ? ((_e = override.requireAvailable) !== null && _e !== void 0 ? _e : base.requireAvailable)
185
+ : false,
167
186
  // `null` is the explicit way to opt out of an agent's default prompt
168
187
  // support; an absent key keeps the default. `undefined` from `??` is
169
188
  // pruned below.
@@ -53,7 +53,12 @@ export interface IEditorSettings {
53
53
  * the editor tile entirely. Defaults to true.
54
54
  */
55
55
  enabled?: boolean;
56
- /** See {@link IEditor.requireAvailable}. */
56
+ /**
57
+ * See {@link IEditor.requireAvailable}. Defaults to true for a built-in
58
+ * editor that still uses its shipped command, and to false once you override
59
+ * the `command` (a user-chosen command — often a shell alias — is trusted and
60
+ * always shown). Set it explicitly to force the check on or off.
61
+ */
57
62
  requireAvailable?: boolean;
58
63
  }
59
64
  /**
@@ -69,7 +74,9 @@ export declare function defaultEditorSettings(): IEditorSettings[];
69
74
  * entries keep their fields unless explicitly overridden; user-only entries are
70
75
  * appended. `enabled: false` filters an entry out of the result entirely (so
71
76
  * callers don't need to re-check the flag). The result is sorted by rank, which
72
- * is also the launcher's tile-preference order. Mirrors `mergeAgents`.
77
+ * is also the launcher's tile-preference order. Mirrors `mergeAgents`, including
78
+ * turning `requireAvailable` off when the user overrides a built-in's `command`
79
+ * so an aliased editor still shows.
73
80
  */
74
81
  export declare function mergeEditors(overrides: IEditorSettings[]): IEditor[];
75
82
  /**
@@ -58,7 +58,9 @@ function resolveEditorIcon(id, iconSvg) {
58
58
  * entries keep their fields unless explicitly overridden; user-only entries are
59
59
  * appended. `enabled: false` filters an entry out of the result entirely (so
60
60
  * callers don't need to re-check the flag). The result is sorted by rank, which
61
- * is also the launcher's tile-preference order. Mirrors `mergeAgents`.
61
+ * is also the launcher's tile-preference order. Mirrors `mergeAgents`, including
62
+ * turning `requireAvailable` off when the user overrides a built-in's `command`
63
+ * so an aliased editor still shows.
62
64
  */
63
65
  export function mergeEditors(overrides) {
64
66
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
@@ -74,16 +76,23 @@ export function mergeEditors(overrides) {
74
76
  if (override.enabled === false) {
75
77
  continue;
76
78
  }
79
+ const command = (_a = override.command) !== null && _a !== void 0 ? _a : base.command;
77
80
  merged.push({
78
81
  id: base.id,
79
- label: (_a = override.label) !== null && _a !== void 0 ? _a : base.label,
80
- caption: (_b = override.caption) !== null && _b !== void 0 ? _b : base.caption,
81
- command: (_c = override.command) !== null && _c !== void 0 ? _c : base.command,
82
+ label: (_b = override.label) !== null && _b !== void 0 ? _b : base.label,
83
+ caption: (_c = override.caption) !== null && _c !== void 0 ? _c : base.caption,
84
+ command,
82
85
  icon: override.iconSvg
83
86
  ? resolveEditorIcon(base.id, override.iconSvg)
84
87
  : base.icon,
85
88
  rank: (_d = override.rank) !== null && _d !== void 0 ? _d : base.rank,
86
- requireAvailable: (_e = override.requireAvailable) !== null && _e !== void 0 ? _e : base.requireAvailable
89
+ // See `mergeAgents`: once the user points a built-in editor at their own
90
+ // command (e.g. a shell alias `which` can't resolve), stop requiring
91
+ // availability so the tile still shows. The check stays on only while the
92
+ // command is xtralab's default.
93
+ requireAvailable: command === base.command
94
+ ? ((_e = override.requireAvailable) !== null && _e !== void 0 ? _e : base.requireAvailable)
95
+ : false
87
96
  });
88
97
  }
89
98
  // What remains in `overrideById` are ids that don't match a built-in — treat
@@ -27,7 +27,9 @@ const PLUGIN_ID = 'xtralab:launcher';
27
27
  * The agent list is the merge of xtralab's defaults with the user's
28
28
  * `xtralab:launcher` settings, then filtered by a server-side `which`
29
29
  * check so users only see agents that are actually installed. Agents with
30
- * `requireAvailable: false` (e.g. shell aliases) skip the filter.
30
+ * `requireAvailable: false` skip the filter, as does any built-in whose
31
+ * `command` the user has overridden (a user-chosen command — often a shell
32
+ * alias the server can't resolve — is trusted and always shown).
31
33
  *
32
34
  * The plugin deliberately does NOT provide the `ILauncher` token: other
33
35
  * extensions register notebook/console/terminal cards on it as a side
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xtralab",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "description": "An opinionated JupyterLab meta-package that bundles a curated set of extensions, ships a path-first file browser, renders jupyterlab-git's text, notebook and image diffs with its own viewers, and applies a quieter default workspace configuration.",
5
5
  "keywords": [
6
6
  "jupyter",
@@ -8,7 +8,7 @@
8
8
  "properties": {
9
9
  "agents": {
10
10
  "title": "Agents",
11
- "description": "Override or extend the built-in list of agents shown on the launcher. Each entry must include an `id`. When the id matches a built-in (claude, codex, antigravity, copilot, goose, opencode, kiro, mistral-vibe), the fields you set override the corresponding defaults; leave a field out to keep the default. New ids define brand-new cards. Set `enabled: false` to hide a default. Set `requireAvailable: false` for shell aliases that should always show even though they aren't on PATH. The full built-in list is shown as the default below, so you can copy an entry and tweak it in place.",
11
+ "description": "Override or extend the built-in list of agents shown on the launcher. Each entry must include an `id`. When the id matches a built-in (claude, codex, antigravity, copilot, goose, opencode, kiro, mistral-vibe), the fields you set override the corresponding defaults; leave a field out to keep the default. New ids define brand-new cards. Set `enabled: false` to hide a default. Changing a built-in's `command` (for example to a shell alias like `ccm`) keeps the card visible even though the alias isn't on PATH; use `requireAvailable: false` only when you want to skip the check without changing the command. The full built-in list is shown as the default below, so you can copy an entry and tweak it in place.",
12
12
  "type": "array",
13
13
  "default": [],
14
14
  "items": {
@@ -54,7 +54,7 @@
54
54
  },
55
55
  "requireAvailable": {
56
56
  "title": "Require available",
57
- "description": "When false, the launcher skips the availability check for this entry (useful for shell aliases that aren't on PATH but resolve in an interactive shell).",
57
+ "description": "When false, the launcher skips the availability check for this entry (useful for shell aliases that aren't on PATH but resolve in an interactive shell). Overriding a built-in agent's command turns this off automatically, so an aliased command still shows; set it explicitly to force the check on or off.",
58
58
  "type": "boolean",
59
59
  "default": true
60
60
  },
@@ -69,7 +69,7 @@
69
69
  },
70
70
  "editors": {
71
71
  "title": "Editors",
72
- "description": "Override or extend the terminal editors offered in the launcher's Open section (and recognized in the Terminals panel). Each entry must include an `id`. When the id matches a built-in (nvim, vim), the fields you set override the corresponding defaults; leave a field out to keep the default. New ids define additional editors. The launcher shows a single tile — the first editor, by `rank`, whose `command` is on PATH (Neovim before Vim by default). Set `enabled: false` to hide a built-in; disable both to remove the tile entirely. Set `requireAvailable: false` for a shell alias that should show even though it isn't on PATH. The full built-in list is shown as the default below, so you can copy an entry and tweak it in place.",
72
+ "description": "Override or extend the terminal editors offered in the launcher's Open section (and recognized in the Terminals panel). Each entry must include an `id`. When the id matches a built-in (nvim, vim), the fields you set override the corresponding defaults; leave a field out to keep the default. New ids define additional editors. The launcher shows a single tile — the first editor, by `rank`, whose `command` is on PATH (Neovim before Vim by default). Set `enabled: false` to hide a built-in; disable both to remove the tile entirely. Changing a built-in's `command` (for example to a shell alias) keeps the tile visible even though the alias isn't on PATH; use `requireAvailable: false` only when you want to skip the check without changing the command. The full built-in list is shown as the default below, so you can copy an entry and tweak it in place.",
73
73
  "type": "array",
74
74
  "default": [],
75
75
  "items": {
@@ -115,7 +115,7 @@
115
115
  },
116
116
  "requireAvailable": {
117
117
  "title": "Require available",
118
- "description": "When false, the launcher skips the availability check for this entry (useful for a shell alias that isn't on PATH but resolves in an interactive shell).",
118
+ "description": "When false, the launcher skips the availability check for this entry (useful for a shell alias that isn't on PATH but resolves in an interactive shell). Overriding a built-in editor's command turns this off automatically, so an aliased command still shows; set it explicitly to force the check on or off.",
119
119
  "type": "boolean",
120
120
  "default": true
121
121
  }
@@ -63,7 +63,12 @@ export interface IAgentSettings {
63
63
  * palette. Defaults to true.
64
64
  */
65
65
  enabled?: boolean;
66
- /** See `IAgent.requireAvailable`. */
66
+ /**
67
+ * See `IAgent.requireAvailable`. Defaults to true for a built-in agent that
68
+ * still uses its shipped command, and to false once you override the
69
+ * `command` (a user-chosen command — often a shell alias — is trusted and
70
+ * always shown). Set it explicitly to force the check on or off.
71
+ */
67
72
  requireAvailable?: boolean;
68
73
  /**
69
74
  * See `IAgent.promptArgs`. Pass an empty array to mark the agent as
@@ -215,6 +220,11 @@ function resolveIcon(id: string, iconSvg: string | undefined): LabIcon {
215
220
  * their built-in fields unless explicitly overridden; user-only entries are
216
221
  * appended. `enabled: false` filters an entry out of the result entirely
217
222
  * (so callers don't need to check the flag again).
223
+ *
224
+ * Overriding a built-in agent's `command` also turns its `requireAvailable`
225
+ * off, so the card survives the launcher's `which`-based availability filter
226
+ * even when the new command is a shell alias the server can't resolve. See the
227
+ * built-in branch below for the rationale.
218
228
  */
219
229
  export function mergeAgents(overrides: IAgentSettings[]): IAgent[] {
220
230
  const overrideById = new Map(overrides.map(entry => [entry.id, entry]));
@@ -230,16 +240,31 @@ export function mergeAgents(overrides: IAgentSettings[]): IAgent[] {
230
240
  if (override.enabled === false) {
231
241
  continue;
232
242
  }
243
+ const command = override.command ?? base.command;
233
244
  merged.push({
234
245
  id: base.id,
235
246
  label: override.label ?? base.label,
236
247
  caption: override.caption ?? base.caption,
237
- command: override.command ?? base.command,
248
+ command,
238
249
  icon: override.iconSvg
239
250
  ? resolveIcon(base.id, override.iconSvg)
240
251
  : base.icon,
241
252
  rank: override.rank ?? base.rank,
242
- requireAvailable: override.requireAvailable ?? base.requireAvailable,
253
+ // The availability filter exists to prune xtralab's *built-in* command
254
+ // from the launcher when it isn't installed. Once the user points the
255
+ // agent at their own command — e.g. the `ccm` alias wrapping `claude
256
+ // --effort=max …` — the server's `shutil.which` probe can't see it
257
+ // (aliases and shell functions only exist inside an interactive shell),
258
+ // so keeping the check on would wrongly hide the card. We therefore only
259
+ // require availability while the command is still xtralab's default; a
260
+ // user-chosen command is trusted and always shown. An explicit
261
+ // `requireAvailable` still applies to the unchanged default command, so a
262
+ // user can alias `claude` itself and set `requireAvailable: false` (or
263
+ // force the check back on).
264
+ requireAvailable:
265
+ command === base.command
266
+ ? (override.requireAvailable ?? base.requireAvailable)
267
+ : false,
243
268
  // `null` is the explicit way to opt out of an agent's default prompt
244
269
  // support; an absent key keeps the default. `undefined` from `??` is
245
270
  // pruned below.
@@ -57,7 +57,12 @@ export interface IEditorSettings {
57
57
  * the editor tile entirely. Defaults to true.
58
58
  */
59
59
  enabled?: boolean;
60
- /** See {@link IEditor.requireAvailable}. */
60
+ /**
61
+ * See {@link IEditor.requireAvailable}. Defaults to true for a built-in
62
+ * editor that still uses its shipped command, and to false once you override
63
+ * the `command` (a user-chosen command — often a shell alias — is trusted and
64
+ * always shown). Set it explicitly to force the check on or off.
65
+ */
61
66
  requireAvailable?: boolean;
62
67
  }
63
68
 
@@ -121,7 +126,9 @@ function resolveEditorIcon(id: string, iconSvg: string | undefined): LabIcon {
121
126
  * entries keep their fields unless explicitly overridden; user-only entries are
122
127
  * appended. `enabled: false` filters an entry out of the result entirely (so
123
128
  * callers don't need to re-check the flag). The result is sorted by rank, which
124
- * is also the launcher's tile-preference order. Mirrors `mergeAgents`.
129
+ * is also the launcher's tile-preference order. Mirrors `mergeAgents`, including
130
+ * turning `requireAvailable` off when the user overrides a built-in's `command`
131
+ * so an aliased editor still shows.
125
132
  */
126
133
  export function mergeEditors(overrides: IEditorSettings[]): IEditor[] {
127
134
  const overrideById = new Map(overrides.map(entry => [entry.id, entry]));
@@ -137,16 +144,24 @@ export function mergeEditors(overrides: IEditorSettings[]): IEditor[] {
137
144
  if (override.enabled === false) {
138
145
  continue;
139
146
  }
147
+ const command = override.command ?? base.command;
140
148
  merged.push({
141
149
  id: base.id,
142
150
  label: override.label ?? base.label,
143
151
  caption: override.caption ?? base.caption,
144
- command: override.command ?? base.command,
152
+ command,
145
153
  icon: override.iconSvg
146
154
  ? resolveEditorIcon(base.id, override.iconSvg)
147
155
  : base.icon,
148
156
  rank: override.rank ?? base.rank,
149
- requireAvailable: override.requireAvailable ?? base.requireAvailable
157
+ // See `mergeAgents`: once the user points a built-in editor at their own
158
+ // command (e.g. a shell alias `which` can't resolve), stop requiring
159
+ // availability so the tile still shows. The check stays on only while the
160
+ // command is xtralab's default.
161
+ requireAvailable:
162
+ command === base.command
163
+ ? (override.requireAvailable ?? base.requireAvailable)
164
+ : false
150
165
  });
151
166
  }
152
167
 
@@ -37,7 +37,9 @@ const PLUGIN_ID = 'xtralab:launcher';
37
37
  * The agent list is the merge of xtralab's defaults with the user's
38
38
  * `xtralab:launcher` settings, then filtered by a server-side `which`
39
39
  * check so users only see agents that are actually installed. Agents with
40
- * `requireAvailable: false` (e.g. shell aliases) skip the filter.
40
+ * `requireAvailable: false` skip the filter, as does any built-in whose
41
+ * `command` the user has overridden (a user-chosen command — often a shell
42
+ * alias the server can't resolve — is trusted and always shown).
41
43
  *
42
44
  * The plugin deliberately does NOT provide the `ILauncher` token: other
43
45
  * extensions register notebook/console/terminal cards on it as a side