xtralab 0.15.0 → 0.15.2
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 +65 -30
- package/lib/about/icons.d.ts +0 -5
- package/lib/about/icons.js +0 -5
- package/lib/about/index.d.ts +4 -8
- package/lib/about/index.js +6 -17
- package/lib/agentSessions.d.ts +9 -29
- package/lib/agentSessions.js +2 -7
- package/lib/askAgent/editorSelection.d.ts +20 -26
- package/lib/askAgent/editorSelection.js +11 -26
- package/lib/askAgent/icons.d.ts +2 -3
- package/lib/askAgent/icons.js +2 -3
- package/lib/askAgent/index.d.ts +4 -26
- package/lib/askAgent/index.js +54 -158
- package/lib/askAgent/popup.d.ts +12 -16
- package/lib/askAgent/popup.js +18 -37
- package/lib/askAgent/prompt.d.ts +3 -5
- package/lib/askAgent/prompt.js +6 -19
- package/lib/askAgent/queue.d.ts +11 -21
- package/lib/askAgent/queue.js +9 -19
- package/lib/askAgent/queuePanel.d.ts +13 -18
- package/lib/askAgent/queuePanel.js +15 -37
- package/lib/askAgent/targetPicker.d.ts +2 -9
- package/lib/askAgent/targetPicker.js +6 -11
- package/lib/askAgent/tokens.d.ts +32 -46
- package/lib/askAgent/tokens.js +4 -6
- package/lib/commandBar/index.d.ts +4 -13
- package/lib/commandBar/index.js +21 -39
- package/lib/customPanel/index.js +15 -0
- package/lib/editorBreadcrumbs/index.d.ts +3 -6
- package/lib/editorBreadcrumbs/index.js +10 -6
- package/lib/editorBreadcrumbs/widget.d.ts +17 -4
- package/lib/editorBreadcrumbs/widget.js +11 -17
- package/lib/editorIndent/index.d.ts +4 -12
- package/lib/editorIndent/index.js +8 -23
- package/lib/fileBrowser/commands.d.ts +29 -19
- package/lib/fileBrowser/commands.js +83 -97
- package/lib/fileBrowser/contents.d.ts +3 -0
- package/lib/fileBrowser/dragAndDrop.d.ts +17 -4
- package/lib/fileBrowser/dragAndDrop.js +2 -7
- package/lib/fileBrowser/fileBrowser.d.ts +19 -9
- package/lib/fileBrowser/fileBrowser.js +70 -222
- package/lib/fileBrowser/gitStatus.d.ts +16 -10
- package/lib/fileBrowser/gitStatus.js +31 -30
- package/lib/fileBrowser/gitignore.d.ts +4 -17
- package/lib/fileBrowser/gitignore.js +4 -25
- package/lib/fileBrowser/icons.d.ts +7 -17
- package/lib/fileBrowser/icons.js +25 -80
- package/lib/fileBrowser/index.js +2 -4
- package/lib/fileBrowser/widget.d.ts +141 -48
- package/lib/fileBrowser/widget.js +102 -4
- package/lib/fileTypeIcons/index.js +0 -10
- package/lib/git/api.d.ts +5 -13
- package/lib/git/api.js +10 -36
- package/lib/git/askRequest.d.ts +4 -8
- package/lib/git/askRequest.js +6 -20
- package/lib/git/commands.d.ts +45 -5
- package/lib/git/commands.js +20 -13
- package/lib/git/diffModel.js +4 -0
- package/lib/git/diffPreferences.d.ts +90 -0
- package/lib/git/diffPreferences.js +107 -0
- package/lib/git/diffProvider.js +10 -2
- package/lib/git/diffSurface.d.ts +64 -63
- package/lib/git/diffSurface.js +72 -213
- package/lib/git/diffTheme.d.ts +7 -0
- package/lib/git/diffTheme.js +23 -0
- package/lib/git/diffWidget.d.ts +70 -14
- package/lib/git/diffWidget.js +100 -94
- package/lib/git/imageDiff.d.ts +14 -6
- package/lib/git/imageDiff.js +19 -75
- package/lib/git/index.d.ts +0 -3
- package/lib/git/index.js +44 -10
- package/lib/git/notebookDiff.d.ts +110 -33
- package/lib/git/notebookDiff.js +55 -197
- package/lib/git/tokens.d.ts +73 -31
- package/lib/git/tokens.js +2 -3
- package/lib/highlight/index.d.ts +4 -10
- package/lib/highlight/index.js +10 -41
- package/lib/index.d.ts +0 -9
- package/lib/index.js +0 -9
- package/lib/launcher/agents.d.ts +55 -51
- package/lib/launcher/agents.js +15 -57
- package/lib/launcher/availability.d.ts +3 -9
- package/lib/launcher/availability.js +3 -9
- package/lib/launcher/commands.d.ts +7 -32
- package/lib/launcher/commands.js +14 -45
- package/lib/launcher/dashboard.d.ts +19 -24
- package/lib/launcher/dashboard.js +21 -67
- package/lib/launcher/editorRegistry.d.ts +10 -22
- package/lib/launcher/editorRegistry.js +14 -18
- package/lib/launcher/editors.d.ts +39 -45
- package/lib/launcher/editors.js +8 -34
- package/lib/launcher/icons.d.ts +0 -12
- package/lib/launcher/icons.js +5 -39
- package/lib/launcher/index.js +12 -55
- package/lib/launcher/invocation.d.ts +4 -10
- package/lib/launcher/invocation.js +7 -22
- package/lib/launcher/registry.d.ts +9 -7
- package/lib/launcher/registry.js +9 -7
- package/lib/launcher/tokens.d.ts +10 -22
- package/lib/launcher/tokens.js +5 -8
- package/lib/menuBar/index.d.ts +3 -10
- package/lib/menuBar/index.js +11 -28
- package/lib/menus/index.d.ts +3 -9
- package/lib/menus/index.js +14 -30
- package/lib/omnibox/files.d.ts +2 -4
- package/lib/omnibox/files.js +5 -11
- package/lib/omnibox/index.d.ts +4 -14
- package/lib/omnibox/index.js +9 -27
- package/lib/omnibox/model.d.ts +38 -10
- package/lib/omnibox/model.js +15 -33
- package/lib/omnibox/recents.d.ts +15 -17
- package/lib/omnibox/recents.js +12 -17
- package/lib/omnibox/tokens.d.ts +5 -10
- package/lib/omnibox/tokens.js +2 -6
- package/lib/omnibox/widget.d.ts +11 -7
- package/lib/omnibox/widget.js +8 -16
- package/lib/searchReplace/index.d.ts +4 -20
- package/lib/searchReplace/index.js +7 -27
- package/lib/showOutput/index.d.ts +3 -12
- package/lib/showOutput/index.js +6 -22
- package/lib/sidebar/index.d.ts +4 -7
- package/lib/sidebar/index.js +5 -12
- package/lib/terminalNotifications/index.d.ts +4 -10
- package/lib/terminalNotifications/index.js +6 -20
- package/lib/terminals/agentTerminals.d.ts +12 -5
- package/lib/terminals/agentTerminals.js +25 -44
- package/lib/terminals/detection.d.ts +4 -8
- package/lib/terminals/detection.js +4 -8
- package/lib/terminals/index.d.ts +0 -35
- package/lib/terminals/index.js +12 -101
- package/lib/terminals/model.d.ts +64 -139
- package/lib/terminals/model.js +80 -220
- package/lib/terminals/tokens.d.ts +11 -22
- package/lib/terminals/tokens.js +2 -2
- package/lib/terminals/widget.d.ts +43 -13
- package/lib/terminals/widget.js +33 -18
- package/lib/topBar/icons.d.ts +3 -8
- package/lib/topBar/icons.js +3 -8
- package/lib/topBar/index.d.ts +4 -11
- package/lib/topBar/index.js +10 -38
- package/lib/walkthrough/index.d.ts +4 -9
- package/lib/walkthrough/index.js +6 -20
- package/lib/walkthrough/panel.d.ts +40 -9
- package/lib/walkthrough/panel.js +4 -10
- package/package.json +5 -3
- package/schema/git-diff-preferences.json +42 -0
- package/src/about/icons.ts +0 -5
- package/src/about/index.tsx +6 -17
- package/src/agentSessions.ts +9 -29
- package/src/askAgent/editorSelection.ts +22 -29
- package/src/askAgent/icons.ts +2 -3
- package/src/askAgent/index.ts +54 -158
- package/src/askAgent/popup.tsx +23 -45
- package/src/askAgent/prompt.ts +6 -19
- package/src/askAgent/queue.ts +13 -24
- package/src/askAgent/queuePanel.tsx +21 -46
- package/src/askAgent/targetPicker.tsx +5 -15
- package/src/askAgent/tokens.ts +32 -46
- package/src/commandBar/index.ts +24 -39
- package/src/customPanel/index.ts +15 -0
- package/src/editorBreadcrumbs/index.ts +10 -6
- package/src/editorBreadcrumbs/widget.ts +23 -17
- package/src/editorIndent/index.ts +17 -23
- package/src/fileBrowser/commands.ts +119 -96
- package/src/fileBrowser/contents.ts +3 -0
- package/src/fileBrowser/dragAndDrop.ts +17 -7
- package/src/fileBrowser/fileBrowser.tsx +86 -230
- package/src/fileBrowser/gitStatus.ts +36 -33
- package/src/fileBrowser/gitignore.ts +4 -25
- package/src/fileBrowser/icons.ts +25 -80
- package/src/fileBrowser/index.ts +2 -4
- package/src/fileBrowser/widget.tsx +171 -50
- package/src/fileTypeIcons/index.ts +0 -10
- package/src/git/api.ts +10 -36
- package/src/git/askRequest.ts +6 -20
- package/src/git/commands.ts +83 -11
- package/src/git/diffModel.ts +25 -0
- package/src/git/diffPreferences.ts +192 -0
- package/src/git/diffProvider.tsx +11 -2
- package/src/git/diffSurface.tsx +165 -286
- package/src/git/diffTheme.ts +24 -0
- package/src/git/diffWidget.tsx +194 -134
- package/src/git/imageDiff.tsx +56 -84
- package/src/git/index.ts +54 -10
- package/src/git/notebookDiff.tsx +214 -240
- package/src/git/tokens.ts +73 -31
- package/src/highlight/index.ts +10 -41
- package/src/index.ts +0 -9
- package/src/launcher/agents.ts +64 -95
- package/src/launcher/availability.ts +3 -9
- package/src/launcher/commands.ts +14 -51
- package/src/launcher/dashboard.tsx +49 -88
- package/src/launcher/editorRegistry.ts +21 -29
- package/src/launcher/editors.ts +39 -58
- package/src/launcher/icons.ts +5 -39
- package/src/launcher/index.ts +12 -55
- package/src/launcher/invocation.ts +7 -22
- package/src/launcher/registry.ts +9 -7
- package/src/launcher/tokens.ts +10 -22
- package/src/menuBar/index.ts +11 -28
- package/src/menus/index.ts +14 -30
- package/src/omnibox/files.ts +10 -14
- package/src/omnibox/index.ts +9 -27
- package/src/omnibox/model.ts +50 -38
- package/src/omnibox/recents.ts +17 -22
- package/src/omnibox/tokens.ts +5 -10
- package/src/omnibox/widget.tsx +14 -19
- package/src/searchReplace/index.ts +7 -27
- package/src/showOutput/index.ts +6 -22
- package/src/sidebar/index.ts +20 -12
- package/src/terminalNotifications/index.ts +42 -25
- package/src/terminals/agentTerminals.ts +25 -49
- package/src/terminals/detection.ts +4 -8
- package/src/terminals/index.ts +12 -101
- package/src/terminals/model.ts +130 -246
- package/src/terminals/tokens.ts +11 -22
- package/src/terminals/widget.tsx +48 -31
- package/src/topBar/icons.ts +3 -8
- package/src/topBar/index.ts +21 -44
- package/src/walkthrough/index.ts +6 -20
- package/src/walkthrough/panel.ts +40 -10
- package/style/about.css +2 -7
- package/style/askAgent.css +8 -40
- package/style/base.css +9 -45
- package/style/chrome.css +108 -308
- package/style/commandBar.css +4 -20
- package/style/customPanel.css +1 -4
- package/style/git.css +26 -186
- package/style/highlight.css +1 -3
- package/style/launcher.css +6 -70
- package/style/omnibox.css +2 -14
- package/style/showOutput.css +0 -6
- package/style/sidebar.css +29 -9
- package/style/tabs.css +5 -13
- package/style/terminals.css +6 -53
- package/style/topBar.css +2 -22
- package/style/walkthrough.css +0 -8
package/lib/highlight/index.js
CHANGED
|
@@ -6,26 +6,16 @@ import { ITranslator, nullTranslator } from '@jupyterlab/translation';
|
|
|
6
6
|
import { StateEffect, StateField } from '@codemirror/state';
|
|
7
7
|
import { Decoration, EditorView } from '@codemirror/view';
|
|
8
8
|
const PLUGIN_ID = 'xtralab:highlight';
|
|
9
|
-
/**
|
|
10
|
-
* Highlight a contiguous range of lines, or clear every highlight. These are
|
|
11
|
-
* the only two commands the plugin contributes; both are designed to be driven
|
|
12
|
-
* by a coding agent over the MCP command bridge to walk a user through code.
|
|
13
|
-
*/
|
|
14
9
|
const HIGHLIGHT_LINES_COMMAND = 'xtralab:highlight-lines';
|
|
15
10
|
const CLEAR_HIGHLIGHTS_COMMAND = 'xtralab:clear-highlights';
|
|
16
|
-
/**
|
|
17
|
-
* CodeMirror line-decoration class; styled in style/highlight.css.
|
|
18
|
-
*/
|
|
19
11
|
const HIGHLIGHT_LINE_CLASS = 'jp-xtralab-highlightLine';
|
|
20
12
|
/**
|
|
21
|
-
*
|
|
22
|
-
* highlight, or `null` to clear the editor's highlights.
|
|
13
|
+
* Carries the 1-indexed inclusive line range to highlight, or `null` to clear.
|
|
23
14
|
*/
|
|
24
15
|
const setHighlight = StateEffect.define();
|
|
25
16
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* editors that are never highlighted pay nothing.
|
|
17
|
+
* Highlight decorations for one editor; injected lazily via
|
|
18
|
+
* `StateEffect.appendConfig` so editors never highlighted pay nothing.
|
|
29
19
|
*/
|
|
30
20
|
const highlightField = StateField.define({
|
|
31
21
|
create: () => Decoration.none,
|
|
@@ -54,11 +44,6 @@ const highlightField = StateField.define({
|
|
|
54
44
|
},
|
|
55
45
|
provide: field => EditorView.decorations.from(field)
|
|
56
46
|
});
|
|
57
|
-
/**
|
|
58
|
-
* Return the CodeMirror view backing a widget's file editor, or `null` when
|
|
59
|
-
* the widget is not a CodeMirror-based text editor (a notebook, a terminal,
|
|
60
|
-
* the settings editor, …).
|
|
61
|
-
*/
|
|
62
47
|
function viewForWidget(widget) {
|
|
63
48
|
const content = widget === null || widget === void 0 ? void 0 : widget.content;
|
|
64
49
|
return content instanceof FileEditor &&
|
|
@@ -66,25 +51,15 @@ function viewForWidget(widget) {
|
|
|
66
51
|
? content.editor.editor
|
|
67
52
|
: null;
|
|
68
53
|
}
|
|
69
|
-
/**
|
|
70
|
-
* Coerce a JSON command argument to a positive integer line number, falling
|
|
71
|
-
* back to `fallback` when it is missing or not a finite number.
|
|
72
|
-
*/
|
|
73
54
|
function toLine(value, fallback) {
|
|
74
55
|
const n = Math.trunc(Number(value));
|
|
75
56
|
return Number.isFinite(n) && n >= 1 ? n : fallback;
|
|
76
57
|
}
|
|
77
58
|
/**
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* highlight a span of lines — `documentsearch:start` only marks text matches
|
|
83
|
-
* and hijacks the find box. This plugin fills that gap with a CodeMirror line
|
|
84
|
-
* decoration, so an agent can point at "lines 31–43 of src/index.ts" while it
|
|
85
|
-
* narrates a walkthrough. `xtralab:highlight-lines` opens the file when needed,
|
|
86
|
-
* scrolls the range into view, and replaces any previous highlight in that
|
|
87
|
-
* editor; `xtralab:clear-highlights` removes every highlight.
|
|
59
|
+
* Contributes `xtralab:highlight-lines` and `xtralab:clear-highlights`,
|
|
60
|
+
* filling the persistent span-highlight gap in the core command surface
|
|
61
|
+
* (`documentsearch:start` only marks text matches and hijacks the find box)
|
|
62
|
+
* so an agent can point at lines while narrating a walkthrough.
|
|
88
63
|
*/
|
|
89
64
|
const plugin = {
|
|
90
65
|
id: PLUGIN_ID,
|
|
@@ -95,8 +70,6 @@ const plugin = {
|
|
|
95
70
|
activate: (app, docManager, palette, translator) => {
|
|
96
71
|
const { commands, shell } = app;
|
|
97
72
|
const trans = (translator !== null && translator !== void 0 ? translator : nullTranslator).load('jupyterlab');
|
|
98
|
-
// Editors that currently carry a highlight, so a single clear can reach
|
|
99
|
-
// them all. Disposed editors are dropped on the next clear.
|
|
100
73
|
const highlighted = new Set();
|
|
101
74
|
const ensureField = (view) => {
|
|
102
75
|
if (view.state.field(highlightField, false) === undefined) {
|
|
@@ -106,8 +79,7 @@ const plugin = {
|
|
|
106
79
|
commands.addCommand(HIGHLIGHT_LINES_COMMAND, {
|
|
107
80
|
label: trans.__('Highlight Lines'),
|
|
108
81
|
caption: trans.__('Highlight a range of lines in a text editor'),
|
|
109
|
-
// Advertise the argument shape
|
|
110
|
-
// bridge can see how to call it, the same way core commands do.
|
|
82
|
+
// Advertise the argument shape to agents listing commands over the MCP bridge.
|
|
111
83
|
describedBy: {
|
|
112
84
|
args: {
|
|
113
85
|
type: 'object',
|
|
@@ -136,9 +108,8 @@ const plugin = {
|
|
|
136
108
|
const endLine = toLine(args['endLine'], line);
|
|
137
109
|
const path = typeof args['path'] === 'string' ? args['path'] : undefined;
|
|
138
110
|
const reveal = args['reveal'] !== false;
|
|
139
|
-
// With a path, bind strictly to that document
|
|
140
|
-
// active widget
|
|
141
|
-
// unrelated editor that happens to be focused.
|
|
111
|
+
// With a path, bind strictly to that document — falling back to the
|
|
112
|
+
// active widget could silently highlight an unrelated editor.
|
|
142
113
|
let widget;
|
|
143
114
|
if (path) {
|
|
144
115
|
// Fail fast on a missing path instead of opening a phantom widget
|
|
@@ -153,7 +124,6 @@ const plugin = {
|
|
|
153
124
|
if (!opened) {
|
|
154
125
|
throw new Error(`xtralab: could not open "${path}"`);
|
|
155
126
|
}
|
|
156
|
-
// Wait for the model and the editor view to be ready.
|
|
157
127
|
await opened.context.ready;
|
|
158
128
|
await opened.revealed;
|
|
159
129
|
widget = opened;
|
|
@@ -179,7 +149,6 @@ const plugin = {
|
|
|
179
149
|
effects.push(EditorView.scrollIntoView(anchor, { y: 'center' }));
|
|
180
150
|
}
|
|
181
151
|
view.dispatch({ effects });
|
|
182
|
-
// Forget editors that have since been closed before tracking this one.
|
|
183
152
|
for (const tracked of highlighted) {
|
|
184
153
|
if (!tracked.dom.isConnected) {
|
|
185
154
|
highlighted.delete(tracked);
|
package/lib/index.d.ts
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
1
|
import { JupyterFrontEndPlugin } from '@jupyterlab/application';
|
|
2
|
-
/**
|
|
3
|
-
* Every plugin contributed by `xtralab`. The entry point of the
|
|
4
|
-
* labextension is an array because the package bundles several independent
|
|
5
|
-
* enhancements (file browser, git diff providers, …) — JupyterLab activates
|
|
6
|
-
* each plugin individually and only the ones whose required tokens are
|
|
7
|
-
* available end up running. `gitPlugins` and `launcherPlugins` are themselves
|
|
8
|
-
* arrays (the git diff providers; the launcher plus its editor registry), so
|
|
9
|
-
* they are spread in.
|
|
10
|
-
*/
|
|
11
2
|
declare const plugins: JupyterFrontEndPlugin<unknown>[];
|
|
12
3
|
export default plugins;
|
package/lib/index.js
CHANGED
|
@@ -20,15 +20,6 @@ import terminalNotificationsPlugin from './terminalNotifications';
|
|
|
20
20
|
import terminalsPlugin from './terminals';
|
|
21
21
|
import topBarPlugin from './topBar';
|
|
22
22
|
import walkthroughPlugin from './walkthrough';
|
|
23
|
-
/**
|
|
24
|
-
* Every plugin contributed by `xtralab`. The entry point of the
|
|
25
|
-
* labextension is an array because the package bundles several independent
|
|
26
|
-
* enhancements (file browser, git diff providers, …) — JupyterLab activates
|
|
27
|
-
* each plugin individually and only the ones whose required tokens are
|
|
28
|
-
* available end up running. `gitPlugins` and `launcherPlugins` are themselves
|
|
29
|
-
* arrays (the git diff providers; the launcher plus its editor registry), so
|
|
30
|
-
* they are spread in.
|
|
31
|
-
*/
|
|
32
23
|
const plugins = [
|
|
33
24
|
aboutPlugin,
|
|
34
25
|
agentSessionsPlugin,
|
package/lib/launcher/agents.d.ts
CHANGED
|
@@ -1,95 +1,99 @@
|
|
|
1
1
|
import { LabIcon } from '@jupyterlab/ui-components';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* aliases, so users can point at `claude`, `cl`, or whatever runs their
|
|
6
|
-
* preferred wrapper.
|
|
3
|
+
* An agent card on the launcher. `command` is the literal text typed into the
|
|
4
|
+
* new terminal, so interactive-shell aliases resolve.
|
|
7
5
|
*/
|
|
8
6
|
export interface IAgent {
|
|
7
|
+
/**
|
|
8
|
+
* Stable id; keys the settings merge and the per-agent launch command.
|
|
9
|
+
*/
|
|
9
10
|
id: string;
|
|
11
|
+
/**
|
|
12
|
+
* Card label, e.g. "Claude".
|
|
13
|
+
*/
|
|
10
14
|
label: string;
|
|
15
|
+
/**
|
|
16
|
+
* Card tooltip; also the palette command caption.
|
|
17
|
+
*/
|
|
11
18
|
caption: string;
|
|
19
|
+
/**
|
|
20
|
+
* The literal command typed into the new terminal.
|
|
21
|
+
*/
|
|
12
22
|
command: string;
|
|
23
|
+
/**
|
|
24
|
+
* Brand icon for the card.
|
|
25
|
+
*/
|
|
13
26
|
icon: LabIcon;
|
|
27
|
+
/**
|
|
28
|
+
* Sort position among the launcher's agent cards.
|
|
29
|
+
*/
|
|
14
30
|
rank: number;
|
|
15
31
|
/**
|
|
16
|
-
* When false,
|
|
17
|
-
*
|
|
18
|
-
* but still resolve when typed in a real terminal. Defaults to true.
|
|
32
|
+
* When false, skip the `which`-based availability check — for aliases or
|
|
33
|
+
* shell functions not on PATH. Defaults to true.
|
|
19
34
|
*/
|
|
20
35
|
requireAvailable: boolean;
|
|
21
36
|
/**
|
|
22
|
-
* Argv tokens spliced between `command` and
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* - `[]` → prompt is appended as a positional argument:
|
|
26
|
-
* `<command> 'PROMPT'`. (Used by claude, codex, vibe, pi.)
|
|
27
|
-
* - `['-i']` / `['--prompt']` → the prompt is preceded by a flag:
|
|
28
|
-
* `<command> -i 'PROMPT'`. (Used by copilot, opencode.)
|
|
29
|
-
* - `undefined` → the agent does not accept an initial prompt. The
|
|
30
|
-
* launcher dims the agent's button while the prompt textarea is
|
|
31
|
-
* non-empty, so the user gets a clear signal rather than a silently
|
|
32
|
-
* dropped prompt.
|
|
33
|
-
*
|
|
34
|
-
* The prompt itself is always single-quoted with embedded single quotes
|
|
35
|
-
* escaped, so multi-line prompts and shell metacharacters are safe.
|
|
37
|
+
* Argv tokens spliced between `command` and the shell-quoted prompt:
|
|
38
|
+
* `[]` appends the prompt positionally, `['-i']` prefixes a flag, and
|
|
39
|
+
* `undefined` means no prompt support (the launcher dims the button).
|
|
36
40
|
*/
|
|
37
41
|
promptArgs?: string[];
|
|
38
42
|
}
|
|
39
43
|
/**
|
|
40
|
-
* The settings-side shape: every field except `id` is optional
|
|
41
|
-
*
|
|
42
|
-
* an alias) without restating the whole entry. New ids define brand-new
|
|
43
|
-
* agent cards.
|
|
44
|
+
* The settings-side shape: every field except `id` is optional so a user can
|
|
45
|
+
* override a single field on a default agent; new ids define new agent cards.
|
|
44
46
|
*/
|
|
45
47
|
export interface IAgentSettings {
|
|
48
|
+
/**
|
|
49
|
+
* Id of the agent to override; a new id defines a new card.
|
|
50
|
+
*/
|
|
46
51
|
id: string;
|
|
52
|
+
/**
|
|
53
|
+
* See `IAgent.label`.
|
|
54
|
+
*/
|
|
47
55
|
label?: string;
|
|
56
|
+
/**
|
|
57
|
+
* See `IAgent.caption`.
|
|
58
|
+
*/
|
|
48
59
|
caption?: string;
|
|
60
|
+
/**
|
|
61
|
+
* See `IAgent.command`.
|
|
62
|
+
*/
|
|
49
63
|
command?: string;
|
|
50
64
|
/**
|
|
51
|
-
* Inline SVG
|
|
52
|
-
*
|
|
53
|
-
* set (in which case it overrides the built-in).
|
|
65
|
+
* Inline SVG icon. Required for new ids; overrides the built-in when set on
|
|
66
|
+
* a default id.
|
|
54
67
|
*/
|
|
55
68
|
iconSvg?: string;
|
|
69
|
+
/**
|
|
70
|
+
* See `IAgent.rank`.
|
|
71
|
+
*/
|
|
56
72
|
rank?: number;
|
|
57
73
|
/**
|
|
58
|
-
* When false, the agent
|
|
59
|
-
* palette. Defaults to true.
|
|
74
|
+
* When false, hides the agent from the launcher and the command palette.
|
|
60
75
|
*/
|
|
61
76
|
enabled?: boolean;
|
|
62
77
|
/**
|
|
63
|
-
* See `IAgent.requireAvailable`. Defaults to true
|
|
64
|
-
*
|
|
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.
|
|
78
|
+
* See `IAgent.requireAvailable`. Defaults to true, but flips to false once
|
|
79
|
+
* `command` is overridden (a user-chosen alias is trusted).
|
|
67
80
|
*/
|
|
68
81
|
requireAvailable?: boolean;
|
|
69
82
|
/**
|
|
70
|
-
* See `IAgent.promptArgs`.
|
|
71
|
-
*
|
|
72
|
-
* flag. Pass `null` to explicitly turn off prompt support for an agent
|
|
73
|
-
* that has it on by default.
|
|
83
|
+
* See `IAgent.promptArgs`. `null` explicitly turns off an agent's default
|
|
84
|
+
* prompt support.
|
|
74
85
|
*/
|
|
75
86
|
promptArgs?: string[] | null;
|
|
76
87
|
}
|
|
77
88
|
/**
|
|
78
|
-
* The built-in agents projected into the
|
|
79
|
-
*
|
|
80
|
-
* {@link registerLauncherSchemaDefaults} injects this as the `agents` setting's
|
|
81
|
-
* schema default so the Settings Editor shows the shipped list.
|
|
89
|
+
* The built-in agents projected into the settings shape (no runtime LabIcon),
|
|
90
|
+
* injected as the `agents` schema default so the Settings Editor shows them.
|
|
82
91
|
*/
|
|
83
92
|
export declare function defaultAgentSettings(): IAgentSettings[];
|
|
84
93
|
/**
|
|
85
|
-
* Merge xtralab's defaults with the user's settings
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
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.
|
|
94
|
+
* Merge xtralab's defaults with the user's settings: defaults keep their
|
|
95
|
+
* fields unless overridden, user-only ids are appended, and `enabled: false`
|
|
96
|
+
* removes an entry entirely. Overriding a built-in's `command` also turns
|
|
97
|
+
* `requireAvailable` off so an aliased command survives the `which` filter.
|
|
94
98
|
*/
|
|
95
99
|
export declare function mergeAgents(overrides: IAgentSettings[]): IAgent[];
|
package/lib/launcher/agents.js
CHANGED
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
import { LabIcon, terminalIcon } from '@jupyterlab/ui-components';
|
|
2
2
|
import { BUILTIN_AGENT_ICONS } from './icons';
|
|
3
3
|
/**
|
|
4
|
-
* Default agent cards
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* terminal rather than the ACP wrapper binaries that project spawns.
|
|
9
|
-
* Antigravity (Google's agent-first IDE/CLI, `agy`) is the Google agent.
|
|
10
|
-
* Pi (https://pi.dev, `earendil-works/pi`) is a minimal extensible coding
|
|
11
|
-
* agent; its mark comes straight from its site. Anything not on the user's
|
|
12
|
-
* `$PATH` is filtered out at activation time, so the wider list is harmless.
|
|
4
|
+
* Default agent cards. Most mirror `jupyter-ai-contrib/jupyter-ai-acp-client`
|
|
5
|
+
* personas but use the bare CLI names a user would type, not the ACP wrappers.
|
|
6
|
+
* Anything not on `$PATH` is filtered out at activation, so the wide list is
|
|
7
|
+
* harmless.
|
|
13
8
|
*/
|
|
14
9
|
const DEFAULTS = [
|
|
15
10
|
{
|
|
@@ -40,13 +35,8 @@ const DEFAULTS = [
|
|
|
40
35
|
icon: BUILTIN_AGENT_ICONS.antigravity,
|
|
41
36
|
rank: 2,
|
|
42
37
|
requireAvailable: true
|
|
43
|
-
// `agy`
|
|
44
|
-
//
|
|
45
|
-
// Its positional args are file/folder paths, so there is no inline
|
|
46
|
-
// natural-language prompt form; like goose/kiro we omit promptArgs so a
|
|
47
|
-
// typed prompt dims the button instead of being mangled into a path.
|
|
48
|
-
// The command stays the bare binary (no `agy .`) so the server-side
|
|
49
|
-
// `shutil.which` availability check still resolves it.
|
|
38
|
+
// `agy` opens the Antigravity editor; its positional args are paths, not
|
|
39
|
+
// prompts, and the bare binary keeps the server-side `which` check working.
|
|
50
40
|
},
|
|
51
41
|
{
|
|
52
42
|
id: 'copilot',
|
|
@@ -56,8 +46,7 @@ const DEFAULTS = [
|
|
|
56
46
|
icon: BUILTIN_AGENT_ICONS.copilot,
|
|
57
47
|
rank: 3,
|
|
58
48
|
requireAvailable: true,
|
|
59
|
-
// `-i
|
|
60
|
-
// auto-execute the prompt; `-p` exits after responding (non-interactive).
|
|
49
|
+
// `-i` starts interactive mode with the prompt; `-p` exits after responding.
|
|
61
50
|
promptArgs: ['-i']
|
|
62
51
|
},
|
|
63
52
|
{
|
|
@@ -68,8 +57,7 @@ const DEFAULTS = [
|
|
|
68
57
|
icon: BUILTIN_AGENT_ICONS.goose,
|
|
69
58
|
rank: 4,
|
|
70
59
|
requireAvailable: true
|
|
71
|
-
// `goose`
|
|
72
|
-
// need to type the prompt after `goose session` starts.
|
|
60
|
+
// `goose` takes no inline prompt; it must be typed after `goose session`.
|
|
73
61
|
},
|
|
74
62
|
{
|
|
75
63
|
id: 'opencode',
|
|
@@ -89,8 +77,7 @@ const DEFAULTS = [
|
|
|
89
77
|
icon: BUILTIN_AGENT_ICONS.kiro,
|
|
90
78
|
rank: 6,
|
|
91
79
|
requireAvailable: true
|
|
92
|
-
//
|
|
93
|
-
// `/chat new <prompt>` slash command, not a CLI argument.
|
|
80
|
+
// Kiro only takes initial prompts via the in-session `/chat new` command.
|
|
94
81
|
},
|
|
95
82
|
{
|
|
96
83
|
id: 'mistral-vibe',
|
|
@@ -110,16 +97,12 @@ const DEFAULTS = [
|
|
|
110
97
|
icon: BUILTIN_AGENT_ICONS.pi,
|
|
111
98
|
rank: 8,
|
|
112
99
|
requireAvailable: true,
|
|
113
|
-
// `pi [messages...]` starts the interactive TUI and sends the messages
|
|
114
|
-
// as the first user prompt, so the positional form applies.
|
|
115
100
|
promptArgs: []
|
|
116
101
|
}
|
|
117
102
|
];
|
|
118
103
|
/**
|
|
119
|
-
* The built-in agents projected into the
|
|
120
|
-
*
|
|
121
|
-
* {@link registerLauncherSchemaDefaults} injects this as the `agents` setting's
|
|
122
|
-
* schema default so the Settings Editor shows the shipped list.
|
|
104
|
+
* The built-in agents projected into the settings shape (no runtime LabIcon),
|
|
105
|
+
* injected as the `agents` schema default so the Settings Editor shows them.
|
|
123
106
|
*/
|
|
124
107
|
export function defaultAgentSettings() {
|
|
125
108
|
return DEFAULTS.map(agent => {
|
|
@@ -131,8 +114,6 @@ export function defaultAgentSettings() {
|
|
|
131
114
|
rank: agent.rank,
|
|
132
115
|
requireAvailable: agent.requireAvailable
|
|
133
116
|
};
|
|
134
|
-
// Omit `promptArgs` for agents that don't take an inline prompt, so the
|
|
135
|
-
// default doesn't show a prompt form they lack.
|
|
136
117
|
if (agent.promptArgs !== undefined) {
|
|
137
118
|
entry.promptArgs = agent.promptArgs;
|
|
138
119
|
}
|
|
@@ -147,15 +128,10 @@ function resolveIcon(id, iconSvg) {
|
|
|
147
128
|
return (_a = BUILTIN_AGENT_ICONS[id]) !== null && _a !== void 0 ? _a : terminalIcon;
|
|
148
129
|
}
|
|
149
130
|
/**
|
|
150
|
-
* Merge xtralab's defaults with the user's settings
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
* Overriding a built-in agent's `command` also turns its `requireAvailable`
|
|
156
|
-
* off, so the card survives the launcher's `which`-based availability filter
|
|
157
|
-
* even when the new command is a shell alias the server can't resolve. See the
|
|
158
|
-
* built-in branch below for the rationale.
|
|
131
|
+
* Merge xtralab's defaults with the user's settings: defaults keep their
|
|
132
|
+
* fields unless overridden, user-only ids are appended, and `enabled: false`
|
|
133
|
+
* removes an entry entirely. Overriding a built-in's `command` also turns
|
|
134
|
+
* `requireAvailable` off so an aliased command survives the `which` filter.
|
|
159
135
|
*/
|
|
160
136
|
export function mergeAgents(overrides) {
|
|
161
137
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
@@ -181,32 +157,14 @@ export function mergeAgents(overrides) {
|
|
|
181
157
|
? resolveIcon(base.id, override.iconSvg)
|
|
182
158
|
: base.icon,
|
|
183
159
|
rank: (_d = override.rank) !== null && _d !== void 0 ? _d : base.rank,
|
|
184
|
-
// The availability filter exists to prune xtralab's *built-in* command
|
|
185
|
-
// from the launcher when it isn't installed. Once the user points the
|
|
186
|
-
// agent at their own command — e.g. the `ccm` alias wrapping `claude
|
|
187
|
-
// --effort=max …` — the server's `shutil.which` probe can't see it
|
|
188
|
-
// (aliases and shell functions only exist inside an interactive shell),
|
|
189
|
-
// so keeping the check on would wrongly hide the card. We therefore only
|
|
190
|
-
// require availability while the command is still xtralab's default; a
|
|
191
|
-
// user-chosen command is trusted and always shown. An explicit
|
|
192
|
-
// `requireAvailable` still applies to the unchanged default command, so a
|
|
193
|
-
// user can alias `claude` itself and set `requireAvailable: false` (or
|
|
194
|
-
// force the check back on).
|
|
195
160
|
requireAvailable: command === base.command
|
|
196
161
|
? ((_e = override.requireAvailable) !== null && _e !== void 0 ? _e : base.requireAvailable)
|
|
197
162
|
: false,
|
|
198
|
-
// `null` is the explicit way to opt out of an agent's default prompt
|
|
199
|
-
// support; an absent key keeps the default. `undefined` from `??` is
|
|
200
|
-
// pruned below.
|
|
201
163
|
promptArgs: override.promptArgs === null
|
|
202
164
|
? undefined
|
|
203
165
|
: ((_f = override.promptArgs) !== null && _f !== void 0 ? _f : base.promptArgs)
|
|
204
166
|
});
|
|
205
167
|
}
|
|
206
|
-
// What remains in `overrideById` are entries with ids that don't match a
|
|
207
|
-
// default — treat them as new agents the user is adding. Skip silently
|
|
208
|
-
// when a required field is missing rather than throwing; the settings
|
|
209
|
-
// schema validates the shape, so this is just a defensive fallback.
|
|
210
168
|
let nextRank = merged.reduce((max, agent) => Math.max(max, agent.rank), -1) + 1;
|
|
211
169
|
for (const entry of overrideById.values()) {
|
|
212
170
|
if (entry.enabled === false) {
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* agent cards.
|
|
6
|
-
*
|
|
7
|
-
* On any failure (server extension not loaded, network error, malformed
|
|
8
|
-
* response) the returned Set is `null` — callers should treat that as
|
|
9
|
-
* "availability unknown" and either fall back to showing all agents or
|
|
10
|
-
* surface the error, depending on context.
|
|
2
|
+
* Ask the server extension's `which`-proxy endpoint which commands resolve on
|
|
3
|
+
* its `$PATH`. Returns `null` on any failure — callers should treat that as
|
|
4
|
+
* "availability unknown", not as "nothing available".
|
|
11
5
|
*/
|
|
12
6
|
export declare function fetchAvailableCommands(commands: string[]): Promise<Set<string> | null>;
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
import { URLExt } from '@jupyterlab/coreutils';
|
|
2
2
|
import { ServerConnection } from '@jupyterlab/services';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* agent cards.
|
|
8
|
-
*
|
|
9
|
-
* On any failure (server extension not loaded, network error, malformed
|
|
10
|
-
* response) the returned Set is `null` — callers should treat that as
|
|
11
|
-
* "availability unknown" and either fall back to showing all agents or
|
|
12
|
-
* surface the error, depending on context.
|
|
4
|
+
* Ask the server extension's `which`-proxy endpoint which commands resolve on
|
|
5
|
+
* its `$PATH`. Returns `null` on any failure — callers should treat that as
|
|
6
|
+
* "availability unknown", not as "nothing available".
|
|
13
7
|
*/
|
|
14
8
|
export async function fetchAvailableCommands(commands) {
|
|
15
9
|
if (commands.length === 0) {
|
|
@@ -5,48 +5,23 @@ import type { CommandRegistry } from '@lumino/commands';
|
|
|
5
5
|
import { type IDisposable } from '@lumino/disposable';
|
|
6
6
|
import type { IAgentSessions } from '../agentSessions';
|
|
7
7
|
import type { IAgent } from './agents';
|
|
8
|
-
/**
|
|
9
|
-
* The command id for opening the launcher.
|
|
10
|
-
*/
|
|
11
8
|
export declare const CREATE_LAUNCHER_COMMAND = "launcher:create";
|
|
12
9
|
/**
|
|
13
|
-
* Register a JupyterLab command per agent
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* Returns a single disposable that tears down every registered command —
|
|
18
|
-
* the launcher disposes the previous set before re-registering on settings
|
|
19
|
-
* changes so the command palette stays in sync with the configured agents.
|
|
20
|
-
*
|
|
21
|
-
* When an `agentSessions` registry is supplied, each launch tags its terminal
|
|
22
|
-
* session with the agent's command, so the terminals panel can badge the row
|
|
23
|
-
* with the agent's logo immediately (before server-side detection confirms
|
|
24
|
-
* it).
|
|
10
|
+
* Register a JupyterLab command per agent that opens a new terminal and types
|
|
11
|
+
* the agent's shell command into it. Returns one disposable tearing down every
|
|
12
|
+
* command, so a settings change can re-register without stale palette entries.
|
|
13
|
+
* `agentSessions`, when given, launch-tags each session for the terminals panel.
|
|
25
14
|
*/
|
|
26
15
|
export declare function registerAgentCommands(app: JupyterFrontEnd, agents: IAgent[], agentSessions?: IAgentSessions | null): IDisposable;
|
|
27
16
|
/**
|
|
28
17
|
* Open a fresh terminal, type `invocation` into it as if the user had, and
|
|
29
|
-
* label the tab.
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* `onSession`, when given, is called once with the new session's name right
|
|
34
|
-
* after the terminal is revealed. Callers use it to optimistically tag the
|
|
35
|
-
* session so the terminals panel can badge it with the agent's (or editor's)
|
|
36
|
-
* logo before server-side detection confirms the running process.
|
|
37
|
-
*
|
|
38
|
-
* Resolves with the host `MainAreaWidget` so the caller can place it — the
|
|
39
|
-
* launcher swaps it into its own tab.
|
|
18
|
+
* label the tab. `onSession` receives the new session's name so callers can
|
|
19
|
+
* launch-tag it for the terminals panel. Resolves with the host
|
|
20
|
+
* `MainAreaWidget` so the caller can place it.
|
|
40
21
|
*/
|
|
41
22
|
export declare function launchInTerminal(commands: CommandRegistry, options: {
|
|
42
23
|
cwd?: string;
|
|
43
|
-
/**
|
|
44
|
-
* The literal command line typed into the fresh terminal.
|
|
45
|
-
*/
|
|
46
24
|
invocation: string;
|
|
47
|
-
/**
|
|
48
|
-
* Tab/title label applied once the command is sent.
|
|
49
|
-
*/
|
|
50
25
|
label: string;
|
|
51
26
|
onSession?: (sessionName: string) => void;
|
|
52
27
|
}): Promise<MainAreaWidget<ITerminal.ITerminal>>;
|
package/lib/launcher/commands.js
CHANGED
|
@@ -1,23 +1,12 @@
|
|
|
1
1
|
import { DisposableSet } from '@lumino/disposable';
|
|
2
2
|
import { buildAgentInvocation } from './invocation';
|
|
3
3
|
import { agentCommandId } from './tokens';
|
|
4
|
-
/**
|
|
5
|
-
* The command id for opening the launcher.
|
|
6
|
-
*/
|
|
7
4
|
export const CREATE_LAUNCHER_COMMAND = 'launcher:create';
|
|
8
5
|
/**
|
|
9
|
-
* Register a JupyterLab command per agent
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* Returns a single disposable that tears down every registered command —
|
|
14
|
-
* the launcher disposes the previous set before re-registering on settings
|
|
15
|
-
* changes so the command palette stays in sync with the configured agents.
|
|
16
|
-
*
|
|
17
|
-
* When an `agentSessions` registry is supplied, each launch tags its terminal
|
|
18
|
-
* session with the agent's command, so the terminals panel can badge the row
|
|
19
|
-
* with the agent's logo immediately (before server-side detection confirms
|
|
20
|
-
* it).
|
|
6
|
+
* Register a JupyterLab command per agent that opens a new terminal and types
|
|
7
|
+
* the agent's shell command into it. Returns one disposable tearing down every
|
|
8
|
+
* command, so a settings change can re-register without stale palette entries.
|
|
9
|
+
* `agentSessions`, when given, launch-tags each session for the terminals panel.
|
|
21
10
|
*/
|
|
22
11
|
export function registerAgentCommands(app, agents, agentSessions = null) {
|
|
23
12
|
const disposables = new DisposableSet();
|
|
@@ -35,9 +24,7 @@ export function registerAgentCommands(app, agents, agentSessions = null) {
|
|
|
35
24
|
cwd,
|
|
36
25
|
invocation,
|
|
37
26
|
label: agent.label,
|
|
38
|
-
//
|
|
39
|
-
// panel can show its logo right away; server-side detection takes
|
|
40
|
-
// over as the source of truth on its next poll.
|
|
27
|
+
// Optimistic tag; server-side detection takes over on its next poll.
|
|
41
28
|
onSession: name => agentSessions === null || agentSessions === void 0 ? void 0 : agentSessions.set(name, agent.command)
|
|
42
29
|
});
|
|
43
30
|
}
|
|
@@ -48,27 +35,17 @@ export function registerAgentCommands(app, agents, agentSessions = null) {
|
|
|
48
35
|
}
|
|
49
36
|
/**
|
|
50
37
|
* Open a fresh terminal, type `invocation` into it as if the user had, and
|
|
51
|
-
* label the tab.
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* `onSession`, when given, is called once with the new session's name right
|
|
56
|
-
* after the terminal is revealed. Callers use it to optimistically tag the
|
|
57
|
-
* session so the terminals panel can badge it with the agent's (or editor's)
|
|
58
|
-
* logo before server-side detection confirms the running process.
|
|
59
|
-
*
|
|
60
|
-
* Resolves with the host `MainAreaWidget` so the caller can place it — the
|
|
61
|
-
* launcher swaps it into its own tab.
|
|
38
|
+
* label the tab. `onSession` receives the new session's name so callers can
|
|
39
|
+
* launch-tag it for the terminals panel. Resolves with the host
|
|
40
|
+
* `MainAreaWidget` so the caller can place it.
|
|
62
41
|
*/
|
|
63
42
|
export async function launchInTerminal(commands, options) {
|
|
64
43
|
const { cwd, invocation, label, onSession } = options;
|
|
65
44
|
const main = (await commands.execute('terminal:create-new', {
|
|
66
45
|
cwd
|
|
67
46
|
}));
|
|
68
|
-
// `
|
|
69
|
-
//
|
|
70
|
-
// awaiting it guarantees the Terminal widget has finished its constructor
|
|
71
|
-
// and connected its session listeners.
|
|
47
|
+
// `revealed` chains off the terminal's `ready` promise, so awaiting it
|
|
48
|
+
// guarantees the widget finished construction and connected its listeners.
|
|
72
49
|
await main.revealed;
|
|
73
50
|
const session = main.content.session;
|
|
74
51
|
onSession === null || onSession === void 0 ? void 0 : onSession(session.name);
|
|
@@ -83,20 +60,12 @@ export async function launchInTerminal(commands, options) {
|
|
|
83
60
|
type: 'stdin',
|
|
84
61
|
content: [invocation + '\r']
|
|
85
62
|
});
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
// `Terminal {N}` when the WebSocket first reports `connected`; we connect
|
|
89
|
-
// *after* that listener (and call `applyLabel` after `sendCommand`), so by
|
|
90
|
-
// the time we run the upstream listener has already had its turn. Programs
|
|
91
|
-
// that publish a real xterm title escape sequence still win —
|
|
92
|
-
// `XTerm.onTitleChange` resets the label whenever it fires.
|
|
63
|
+
// XTerm's `_initialConnection` resets the title on first connect; we run
|
|
64
|
+
// after it, so this label survives. A title escape still wins (`onTitleChange`).
|
|
93
65
|
applyLabel();
|
|
94
66
|
};
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
// `connectionStatusChanged` that flips it to `connected`. Without this the
|
|
98
|
-
// stdin write races the websocket handshake and the command silently
|
|
99
|
-
// disappears.
|
|
67
|
+
// Without waiting for `connected` the stdin write races the websocket
|
|
68
|
+
// handshake and the command silently disappears.
|
|
100
69
|
if (session.connectionStatus === 'connected') {
|
|
101
70
|
sendCommand();
|
|
102
71
|
}
|