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/src/terminals/tokens.ts
CHANGED
|
@@ -12,16 +12,13 @@ export interface IAgentTerminalSession {
|
|
|
12
12
|
name: string;
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* The agent identifier
|
|
16
|
-
*
|
|
17
|
-
* is an alias (e.g. `ccm` spawning `claude`). Matches an `IAgent` by
|
|
18
|
-
* either field.
|
|
15
|
+
* The agent identifier detection reported: the configured `command`, or the
|
|
16
|
+
* canonical `id` when the command is an alias (e.g. `ccm` spawning `claude`).
|
|
19
17
|
*/
|
|
20
18
|
command: string;
|
|
21
19
|
|
|
22
20
|
/**
|
|
23
|
-
* Display label — the session's real
|
|
24
|
-
* whatever the running program published via an xterm escape sequence).
|
|
21
|
+
* Display label — the session's real (program-published) title.
|
|
25
22
|
*/
|
|
26
23
|
label: string;
|
|
27
24
|
|
|
@@ -35,12 +32,9 @@ export interface IAgentTerminalSession {
|
|
|
35
32
|
/**
|
|
36
33
|
* Running agent terminals, and a way to send a prompt into one.
|
|
37
34
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* TUI can meaningfully receive pasted prompt text. `sendPrompt` re-validates
|
|
42
|
-
* against the server before writing, since pasting prose into a shell prompt
|
|
43
|
-
* would execute it.
|
|
35
|
+
* Only sessions with a detection-*confirmed* running agent are listed — never
|
|
36
|
+
* optimistic launch tags: pasted prompt text must land in an agent's TUI, not
|
|
37
|
+
* a shell prompt where it would be executed.
|
|
44
38
|
*/
|
|
45
39
|
export interface IAgentTerminals {
|
|
46
40
|
/**
|
|
@@ -54,22 +48,17 @@ export interface IAgentTerminals {
|
|
|
54
48
|
readonly changed: ISignal<IAgentTerminals, void>;
|
|
55
49
|
|
|
56
50
|
/**
|
|
57
|
-
* Paste `prompt` into the named session
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* the session's websocket, bracketed-paste-wrapped so a multi-line prompt
|
|
61
|
-
* arrives as one block in the agent's input box, without revealing or
|
|
62
|
-
* focusing the terminal's tab — the user keeps working where they are,
|
|
63
|
-
* and the agent CLIs queue the prompt themselves when they are busy.
|
|
64
|
-
* Rejects when the session is gone or no agent is running in it anymore.
|
|
51
|
+
* Paste `prompt` (bracketed-paste-wrapped) into the named session and press
|
|
52
|
+
* Enter, writing straight to its websocket without revealing or focusing
|
|
53
|
+
* its tab. Rejects when the session is gone or no agent runs in it anymore.
|
|
65
54
|
*/
|
|
66
55
|
sendPrompt(name: string, prompt: string): Promise<void>;
|
|
67
56
|
}
|
|
68
57
|
|
|
69
58
|
/**
|
|
70
59
|
* DI token for {@link IAgentTerminals}. Provided by `xtralab:terminals`;
|
|
71
|
-
* consumed
|
|
72
|
-
*
|
|
60
|
+
* consumed optionally by `xtralab:ask-agent`, so each side works without
|
|
61
|
+
* the other.
|
|
73
62
|
*/
|
|
74
63
|
export const IAgentTerminals = new Token<IAgentTerminals>(
|
|
75
64
|
'xtralab:IAgentTerminals',
|
package/src/terminals/widget.tsx
CHANGED
|
@@ -25,15 +25,10 @@ import * as React from 'react';
|
|
|
25
25
|
|
|
26
26
|
import { SessionRegistry } from './model';
|
|
27
27
|
|
|
28
|
-
/**
|
|
29
|
-
* Id of the panel widget. Used for layout restoration and as the handle
|
|
30
|
-
* the sidebar visibility toggle would target.
|
|
31
|
-
*/
|
|
32
28
|
const RUNNING_TERMINALS_ID = 'xtralab-running-terminals';
|
|
33
29
|
|
|
34
30
|
/**
|
|
35
|
-
*
|
|
36
|
-
* movable-sections plugin, so it must stay stable across releases.
|
|
31
|
+
* Persisted by the movable-sections plugin — must stay stable across releases.
|
|
37
32
|
*/
|
|
38
33
|
const TERMINALS_SECTION_ID = 'xtralab-terminals-section';
|
|
39
34
|
|
|
@@ -75,8 +70,6 @@ export class RunningTerminals
|
|
|
75
70
|
const newTerminal = new ToolbarButton({
|
|
76
71
|
icon: addIcon,
|
|
77
72
|
onClick: () => {
|
|
78
|
-
// Anchor whatever the plugin shows (usually an agent menu) to the
|
|
79
|
-
// button's bottom-left, in the viewport coordinates `Menu.open` wants.
|
|
80
73
|
const rect = newTerminal.node.getBoundingClientRect();
|
|
81
74
|
options.onCreate({ x: rect.left, y: rect.bottom });
|
|
82
75
|
},
|
|
@@ -97,23 +90,39 @@ export class RunningTerminals
|
|
|
97
90
|
this.addWidget(section);
|
|
98
91
|
}
|
|
99
92
|
|
|
93
|
+
/**
|
|
94
|
+
* The accordion panel hosting the sections; read by the move plugin.
|
|
95
|
+
*/
|
|
100
96
|
get accordionPanel(): AccordionPanel {
|
|
101
97
|
return this.content as AccordionPanel;
|
|
102
98
|
}
|
|
103
99
|
|
|
100
|
+
/**
|
|
101
|
+
* A signal emitted when a section is announced to the move plugin.
|
|
102
|
+
*/
|
|
104
103
|
get sectionAdded(): ISignal<this, ISectionEntry> {
|
|
105
104
|
return this._sectionAdded;
|
|
106
105
|
}
|
|
107
106
|
|
|
107
|
+
/**
|
|
108
|
+
* The hosted section widgets, excluding the panel's own Terminals section.
|
|
109
|
+
*/
|
|
108
110
|
get sections(): ReadonlyArray<Widget> {
|
|
109
111
|
return this.accordionPanel.widgets.filter(w => w !== this._section);
|
|
110
112
|
}
|
|
111
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Get the movable sections: just the Terminals section, while attached here.
|
|
116
|
+
*/
|
|
112
117
|
getSections(): ReadonlyArray<ISectionEntry> {
|
|
113
118
|
const entry = this._sectionEntry();
|
|
114
119
|
return entry ? [entry] : [];
|
|
115
120
|
}
|
|
116
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Detach the Terminals section for the move plugin and return it; `null`
|
|
124
|
+
* for an unknown id or when the section is already hosted elsewhere.
|
|
125
|
+
*/
|
|
117
126
|
removeSectionById(sectionId: string): Widget | null {
|
|
118
127
|
if (
|
|
119
128
|
sectionId !== TERMINALS_SECTION_ID ||
|
|
@@ -125,14 +134,23 @@ export class RunningTerminals
|
|
|
125
134
|
return this._section;
|
|
126
135
|
}
|
|
127
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Re-attach the Terminals section after it moves back to this panel.
|
|
139
|
+
*/
|
|
128
140
|
reinsertSection(widget: Widget): void {
|
|
129
141
|
this.addWidget(widget);
|
|
130
142
|
}
|
|
131
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Host a section moved in from another sidebar panel.
|
|
146
|
+
*/
|
|
132
147
|
addSection(widget: Widget): void {
|
|
133
148
|
this.addWidget(widget);
|
|
134
149
|
}
|
|
135
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Detach a hosted section when it moves back to its own panel.
|
|
153
|
+
*/
|
|
136
154
|
removeSectionWidget(widget: Widget): void {
|
|
137
155
|
if (widget.parent === this.content) {
|
|
138
156
|
widget.parent = null;
|
|
@@ -162,12 +180,14 @@ export class RunningTerminals
|
|
|
162
180
|
}
|
|
163
181
|
}
|
|
164
182
|
|
|
183
|
+
/**
|
|
184
|
+
* Dispose of the panel and the registry it owns.
|
|
185
|
+
*/
|
|
165
186
|
dispose(): void {
|
|
166
187
|
if (this.isDisposed) {
|
|
167
188
|
return;
|
|
168
189
|
}
|
|
169
|
-
// The panel owns the registry
|
|
170
|
-
// subscriptions before the React tree goes away.
|
|
190
|
+
// The panel owns the registry; tear down its subscriptions first.
|
|
171
191
|
this._registry.dispose();
|
|
172
192
|
super.dispose();
|
|
173
193
|
}
|
|
@@ -192,19 +212,25 @@ export class RunningTerminals
|
|
|
192
212
|
}
|
|
193
213
|
|
|
194
214
|
export namespace RunningTerminals {
|
|
215
|
+
/**
|
|
216
|
+
* The instantiation options for a {@link RunningTerminals} panel.
|
|
217
|
+
*/
|
|
195
218
|
export interface IOptions {
|
|
219
|
+
/**
|
|
220
|
+
* The session registry the panel renders and takes ownership of.
|
|
221
|
+
*/
|
|
196
222
|
registry: SessionRegistry;
|
|
223
|
+
/**
|
|
224
|
+
* The translation bundle for the panel's labels; untranslated if omitted.
|
|
225
|
+
*/
|
|
197
226
|
trans?: TranslationBundle;
|
|
198
227
|
/**
|
|
199
|
-
* Resolve
|
|
200
|
-
*
|
|
201
|
-
* the agent's logo, or the plain terminal icon. Supplied by the plugin
|
|
202
|
-
* so the widget never imports the agent list.
|
|
228
|
+
* Resolve a row's running-agent command to its icon; supplied by the
|
|
229
|
+
* plugin so the widget never imports the agent list.
|
|
203
230
|
*/
|
|
204
231
|
iconForCommand: (command: string | null) => LabIcon;
|
|
205
232
|
/**
|
|
206
|
-
* Activate the named session's open tab, or reopen it in a fresh
|
|
207
|
-
* terminal widget if no tab is currently attached.
|
|
233
|
+
* Activate the named session's open tab, or reopen it in a fresh widget.
|
|
208
234
|
*/
|
|
209
235
|
onActivate: (sessionName: string) => void;
|
|
210
236
|
/**
|
|
@@ -212,16 +238,12 @@ export namespace RunningTerminals {
|
|
|
212
238
|
*/
|
|
213
239
|
onShutdown: (sessionName: string) => void;
|
|
214
240
|
/**
|
|
215
|
-
* Shut down every running terminal
|
|
216
|
-
* confirm with the user first, since it tears down all live sessions.
|
|
241
|
+
* Shut down every running terminal; the plugin confirms with the user first.
|
|
217
242
|
*/
|
|
218
243
|
onShutdownAll: () => void;
|
|
219
244
|
/**
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
* there — a menu of agents plus a plain terminal, or just a new
|
|
223
|
-
* terminal when no agents are available — so the panel only reports
|
|
224
|
-
* where the button is and never imports the command/menu machinery.
|
|
245
|
+
* Handle the "+" button, anchored at its bottom-left in viewport
|
|
246
|
+
* coordinates; the plugin decides what to show there.
|
|
225
247
|
*/
|
|
226
248
|
onCreate: (anchor: { x: number; y: number }) => void;
|
|
227
249
|
}
|
|
@@ -243,6 +265,9 @@ class TerminalsListing extends ReactWidget {
|
|
|
243
265
|
this.addClass('jp-xtralab-Terminals-listing');
|
|
244
266
|
}
|
|
245
267
|
|
|
268
|
+
/**
|
|
269
|
+
* Render the listing, re-rendering on every registry state change.
|
|
270
|
+
*/
|
|
246
271
|
protected render(): React.ReactElement {
|
|
247
272
|
return (
|
|
248
273
|
<UseSignal signal={this._options.registry.stateChanged}>
|
|
@@ -277,9 +302,6 @@ function RunningTerminalsComponent(props: {
|
|
|
277
302
|
}): React.ReactElement {
|
|
278
303
|
const { registry, trans, iconForCommand, onActivate, onShutdown } = props;
|
|
279
304
|
const names = registry.sessionNames();
|
|
280
|
-
// The session whose terminal is the current widget in the main area, so its
|
|
281
|
-
// row can be highlighted. `null` when the current tab is a notebook or any
|
|
282
|
-
// other non-terminal widget.
|
|
283
305
|
const currentName = registry.currentSessionName();
|
|
284
306
|
|
|
285
307
|
return (
|
|
@@ -296,15 +318,10 @@ function RunningTerminalsComponent(props: {
|
|
|
296
318
|
const tooltip = hasWidget
|
|
297
319
|
? trans.__('Activate %1', label)
|
|
298
320
|
: trans.__('Reopen %1', label);
|
|
299
|
-
// The running agent's logo (e.g. Claude), or the plain terminal
|
|
300
|
-
// icon when nothing recognised is running in the session.
|
|
301
321
|
const RowIcon = iconForCommand(
|
|
302
322
|
registry.agentCommandFor(name)
|
|
303
323
|
).react;
|
|
304
324
|
const isCurrent = name === currentName;
|
|
305
|
-
// The latest line of output from the session's agent, shown as a
|
|
306
|
-
// smaller line under the title; `null` for rows with nothing to
|
|
307
|
-
// surface (no agent running, or no open tab to read a live buffer).
|
|
308
325
|
const activity = registry.activityFor(name);
|
|
309
326
|
return (
|
|
310
327
|
<li
|
package/src/topBar/icons.ts
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import { LabIcon } from '@jupyterlab/ui-components';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Mirror-symmetric "toggle sidebar" marks
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* by a divider, with the controlled side shaded so left vs. right reads at a
|
|
8
|
-
* glance. The artwork is hand-authored from basic geometry (rounded rect +
|
|
9
|
-
* divider + a shaded panel) so there is no third-party licensing to track,
|
|
10
|
-
* and every stroke/fill uses `currentColor` so the icons inherit the top
|
|
11
|
-
* bar's text color across the light and dark themes.
|
|
4
|
+
* Mirror-symmetric "toggle sidebar" marks in the macOS / VS Code visual
|
|
5
|
+
* language. Hand-authored from basic geometry (no third-party licensing);
|
|
6
|
+
* every stroke/fill uses `currentColor` to follow the top bar's text color.
|
|
12
7
|
*/
|
|
13
8
|
|
|
14
9
|
export const leftSidebarIcon = new LabIcon({
|
package/src/topBar/index.ts
CHANGED
|
@@ -10,16 +10,12 @@ import { leftSidebarIcon, rightSidebarIcon } from './icons';
|
|
|
10
10
|
|
|
11
11
|
const PLUGIN_ID = 'xtralab:top-bar';
|
|
12
12
|
|
|
13
|
-
/**
|
|
14
|
-
* Upstream commands from `@jupyterlab/application-extension` that collapse or
|
|
15
|
-
* expand the side areas. We bind the buttons to these rather than
|
|
16
|
-
* reimplementing the toggle, so behavior (and the `isToggled`/`isEnabled`
|
|
17
|
-
* state the buttons reflect) stays in lockstep with the View menu entries
|
|
18
|
-
* and their keyboard shortcuts.
|
|
19
|
-
*/
|
|
20
13
|
const TOGGLE_LEFT_AREA = 'application:toggle-left-area';
|
|
21
14
|
const TOGGLE_RIGHT_AREA = 'application:toggle-right-area';
|
|
22
15
|
|
|
16
|
+
/**
|
|
17
|
+
* A specification for one sidebar toggle button in the top area.
|
|
18
|
+
*/
|
|
23
19
|
interface IButtonSpec {
|
|
24
20
|
/**
|
|
25
21
|
* Stable widget id (required by `LabShell.add`).
|
|
@@ -29,15 +25,17 @@ interface IButtonSpec {
|
|
|
29
25
|
* Command the button triggers and mirrors the state of.
|
|
30
26
|
*/
|
|
31
27
|
command: string;
|
|
28
|
+
/**
|
|
29
|
+
* The icon rendered on the button.
|
|
30
|
+
*/
|
|
32
31
|
icon: LabIcon;
|
|
32
|
+
/**
|
|
33
|
+
* The localized tooltip of the button.
|
|
34
|
+
*/
|
|
33
35
|
caption: (trans: ReturnType<ITranslator['load']>) => string;
|
|
34
36
|
/**
|
|
35
|
-
* Rank
|
|
36
|
-
*
|
|
37
|
-
* rank puts the right button after the menu, where `margin-left: auto`
|
|
38
|
-
* (style/topBar.css) floats it to the far edge. xtralab's shipped config
|
|
39
|
-
* disables the upstream Jupyter logo that otherwise occupies rank 0, so the
|
|
40
|
-
* leading edge is free.
|
|
37
|
+
* Rank in the `top` area: the menu bar sits at 100 and the rank-0 upstream
|
|
38
|
+
* logo is disabled; `margin-left: auto` (topBar.css) floats the right button.
|
|
41
39
|
*/
|
|
42
40
|
rank: number;
|
|
43
41
|
/**
|
|
@@ -66,17 +64,10 @@ const BUTTONS: IButtonSpec[] = [
|
|
|
66
64
|
];
|
|
67
65
|
|
|
68
66
|
/**
|
|
69
|
-
* Add
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* Each is a `CommandToolbarButton` wrapping an existing
|
|
74
|
-
* `application:toggle-{left,right}-area` command, so clicking it runs the
|
|
75
|
-
* same toggle as the View menu and the button reflects the command's state —
|
|
76
|
-
* pressed while the matching sidebar is open, and disabled when the area is
|
|
77
|
-
* empty. Note xtralab ships nothing in the right area by default (the
|
|
78
|
-
* property inspector, table of contents and debugger are all disabled), so
|
|
79
|
-
* the right button stays disabled until a widget is moved or added there.
|
|
67
|
+
* Add macOS-style sidebar toggle buttons to the top bar: left at the leading
|
|
68
|
+
* edge, right at the far edge. Each wraps the upstream toggle command and
|
|
69
|
+
* reflects its state — pressed while the sidebar is open, disabled while the
|
|
70
|
+
* area is empty (as the right area is by default).
|
|
80
71
|
*/
|
|
81
72
|
const plugin: JupyterFrontEndPlugin<void> = {
|
|
82
73
|
id: PLUGIN_ID,
|
|
@@ -92,40 +83,26 @@ const plugin: JupyterFrontEndPlugin<void> = {
|
|
|
92
83
|
const { commands } = app;
|
|
93
84
|
const trans = (translator ?? nullTranslator).load('jupyterlab');
|
|
94
85
|
|
|
95
|
-
// The upstream toggle
|
|
96
|
-
//
|
|
97
|
-
// move in or out of a side area. `CommandToolbarButton` only re-renders on
|
|
98
|
-
// `commandChanged` for its own id, so the buttons need an explicit notify
|
|
99
|
-
// whenever the shell layout shifts — `layoutModified` covers each side
|
|
100
|
-
// handler's `_updated` (add/remove, expand/collapse), keeping both
|
|
101
|
-
// `isEnabled` and `isToggled` in sync.
|
|
86
|
+
// The upstream toggle commands don't fire `commandChanged` on layout
|
|
87
|
+
// shifts, and `CommandToolbarButton` only re-renders on that signal.
|
|
102
88
|
labShell.layoutModified.connect(() => {
|
|
103
89
|
for (const spec of BUTTONS) {
|
|
104
90
|
commands.notifyCommandChanged(spec.command);
|
|
105
91
|
}
|
|
106
92
|
});
|
|
107
93
|
|
|
108
|
-
// Defer to `app.restored`
|
|
109
|
-
//
|
|
110
|
-
// exists and only re-renders on `commandChanged` of type `changed` /
|
|
111
|
-
// `many-changed` (not `added`), so mounting earlier could leave a button
|
|
112
|
-
// blank until the next unrelated command change.
|
|
94
|
+
// Defer to `app.restored`: `CommandToolbarButton` renders nothing until
|
|
95
|
+
// its command exists and doesn't re-render on the `added` change type.
|
|
113
96
|
void app.restored.then(() => {
|
|
114
97
|
for (const spec of BUTTONS) {
|
|
115
98
|
const button = new CommandToolbarButton({
|
|
116
99
|
commands,
|
|
117
100
|
id: spec.command,
|
|
118
101
|
icon: spec.icon,
|
|
119
|
-
// Empty label keeps the button icon-only: the override is forwarded
|
|
120
|
-
// verbatim and the component skips the label span when it is falsy.
|
|
121
102
|
label: '',
|
|
122
103
|
caption: spec.caption(trans),
|
|
123
|
-
//
|
|
124
|
-
//
|
|
125
|
-
// leaving the stealth button showing a focus fill/outline (the
|
|
126
|
-
// stray "border") until you click elsewhere — unwanted chrome for a
|
|
127
|
-
// title-bar control. Keyboard Tab focus still works, so this stays
|
|
128
|
-
// accessible.
|
|
104
|
+
// ToolbarButtonComponent otherwise focuses the button on click,
|
|
105
|
+
// leaving a stray focus fill on this title-bar control; Tab still works.
|
|
129
106
|
noFocusOnClick: true
|
|
130
107
|
});
|
|
131
108
|
button.id = spec.id;
|
package/src/walkthrough/index.ts
CHANGED
|
@@ -14,18 +14,12 @@ import { IWalkthroughMedia, IWalkthroughStep, WalkthroughPanel } from './panel';
|
|
|
14
14
|
|
|
15
15
|
const PLUGIN_ID = 'xtralab:walkthrough';
|
|
16
16
|
|
|
17
|
-
/**
|
|
18
|
-
* Append a step to the read-only walkthrough panel.
|
|
19
|
-
*/
|
|
20
17
|
const WALKTHROUGH_COMMAND = 'xtralab:walkthrough';
|
|
21
18
|
|
|
22
19
|
const HIGHLIGHT_LINES_COMMAND = 'xtralab:highlight-lines';
|
|
23
20
|
|
|
24
21
|
const PANEL_ID = 'xtralab-walkthrough';
|
|
25
22
|
|
|
26
|
-
/**
|
|
27
|
-
* Pull a `{ mimeType, data }` media object out of a JSON command argument.
|
|
28
|
-
*/
|
|
29
23
|
function readMedia(value: unknown): IWalkthroughMedia | undefined {
|
|
30
24
|
if (
|
|
31
25
|
value &&
|
|
@@ -54,15 +48,10 @@ function toLine(value: unknown): number | undefined {
|
|
|
54
48
|
}
|
|
55
49
|
|
|
56
50
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* optional code reference). When a step names a file, the editor follows along
|
|
62
|
-
* (opening it full-width in the main area, no split) and its lines are
|
|
63
|
-
* highlighted; the step also keeps a button so the user can jump back to it
|
|
64
|
-
* later. The panel accumulates the whole tour beside the code, so the user can
|
|
65
|
-
* read at their own pace rather than chasing the chat.
|
|
51
|
+
* Contributes `xtralab:walkthrough`: each call appends a step (Markdown prose,
|
|
52
|
+
* optional visual, optional code reference) to a persistent read-only panel in
|
|
53
|
+
* the right side area, so the tour accumulates beside the code instead of
|
|
54
|
+
* scrolling away in the agent's chat.
|
|
66
55
|
*/
|
|
67
56
|
const plugin: JupyterFrontEndPlugin<void> = {
|
|
68
57
|
id: PLUGIN_ID,
|
|
@@ -89,9 +78,8 @@ const plugin: JupyterFrontEndPlugin<void> = {
|
|
|
89
78
|
panel.title.icon = tocIcon;
|
|
90
79
|
panel.title.label = trans.__('Walkthrough');
|
|
91
80
|
panel.title.caption = trans.__('Walkthrough');
|
|
92
|
-
// Closable so
|
|
93
|
-
//
|
|
94
|
-
// xtralab:walkthrough call recreates it back in the side area.
|
|
81
|
+
// Closable so a drag into the main area gets a close button; closing
|
|
82
|
+
// disposes, and the next call recreates the panel in the side area.
|
|
95
83
|
panel.title.closable = true;
|
|
96
84
|
labShell.add(panel, 'right', { rank: 1000, type: 'Walkthrough' });
|
|
97
85
|
const created = panel;
|
|
@@ -188,11 +176,9 @@ const plugin: JupyterFrontEndPlugin<void> = {
|
|
|
188
176
|
);
|
|
189
177
|
}
|
|
190
178
|
|
|
191
|
-
// Reveal the panel, then render the step into it.
|
|
192
179
|
labShell.activateById(current.id);
|
|
193
180
|
await current.addStep(step);
|
|
194
181
|
|
|
195
|
-
// Let the editor follow the newest step.
|
|
196
182
|
if (path && args['reveal'] !== false) {
|
|
197
183
|
await commands.execute(HIGHLIGHT_LINES_COMMAND, {
|
|
198
184
|
path,
|
package/src/walkthrough/panel.ts
CHANGED
|
@@ -15,7 +15,13 @@ const HIGHLIGHT_LINES_COMMAND = 'xtralab:highlight-lines';
|
|
|
15
15
|
* A rich visual embedded in a step (rendered through the rendermime registry).
|
|
16
16
|
*/
|
|
17
17
|
export interface IWalkthroughMedia {
|
|
18
|
+
/**
|
|
19
|
+
* The MIME type of the media payload.
|
|
20
|
+
*/
|
|
18
21
|
mimeType: string;
|
|
22
|
+
/**
|
|
23
|
+
* The payload handed to the renderer for the MIME type.
|
|
24
|
+
*/
|
|
19
25
|
data: ReadonlyPartialJSONValue;
|
|
20
26
|
}
|
|
21
27
|
|
|
@@ -23,30 +29,56 @@ export interface IWalkthroughMedia {
|
|
|
23
29
|
* One step of a walkthrough. Every field is optional, but a step needs at least one.
|
|
24
30
|
*/
|
|
25
31
|
export interface IWalkthroughStep {
|
|
32
|
+
/**
|
|
33
|
+
* A heading rendered above the step content.
|
|
34
|
+
*/
|
|
26
35
|
title?: string;
|
|
36
|
+
/**
|
|
37
|
+
* The body of the step, rendered as Markdown.
|
|
38
|
+
*/
|
|
27
39
|
body?: string;
|
|
40
|
+
/**
|
|
41
|
+
* A rich visual rendered after the body.
|
|
42
|
+
*/
|
|
28
43
|
media?: IWalkthroughMedia;
|
|
44
|
+
/**
|
|
45
|
+
* The file the step points at; when set, the step renders a jump link.
|
|
46
|
+
*/
|
|
29
47
|
path?: string;
|
|
48
|
+
/**
|
|
49
|
+
* The first line to highlight when the jump link is followed.
|
|
50
|
+
*/
|
|
30
51
|
line?: number;
|
|
52
|
+
/**
|
|
53
|
+
* The last line of the highlighted range.
|
|
54
|
+
*/
|
|
31
55
|
endLine?: number;
|
|
32
56
|
}
|
|
33
57
|
|
|
34
58
|
export namespace WalkthroughPanel {
|
|
59
|
+
/**
|
|
60
|
+
* The instantiation options for a walkthrough panel.
|
|
61
|
+
*/
|
|
35
62
|
export interface IOptions {
|
|
63
|
+
/**
|
|
64
|
+
* The rendermime registry used to render step bodies and media.
|
|
65
|
+
*/
|
|
36
66
|
rendermime: IRenderMimeRegistry;
|
|
67
|
+
/**
|
|
68
|
+
* The command registry used to execute the jump-to-line command.
|
|
69
|
+
*/
|
|
37
70
|
commands: CommandRegistry;
|
|
71
|
+
/**
|
|
72
|
+
* The translation bundle for UI strings.
|
|
73
|
+
*/
|
|
38
74
|
trans: TranslationBundle;
|
|
39
75
|
}
|
|
40
76
|
}
|
|
41
77
|
|
|
42
78
|
/**
|
|
43
79
|
* A read-only, scrollable column of walkthrough steps for the side area.
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* code the user is looking at and persists for them to read at their own pace,
|
|
47
|
-
* rather than scrolling away in the chat. Each step renders Markdown (with code
|
|
48
|
-
* snippets, Mermaid, math), can embed a rich visual, and can offer a button
|
|
49
|
-
* that opens the referenced file and highlights its lines.
|
|
80
|
+
* The agent appends steps as it narrates, so the explanation persists beside
|
|
81
|
+
* the code instead of scrolling away in the chat.
|
|
50
82
|
*/
|
|
51
83
|
export class WalkthroughPanel extends Panel {
|
|
52
84
|
constructor(options: WalkthroughPanel.IOptions) {
|
|
@@ -67,9 +99,8 @@ export class WalkthroughPanel extends Panel {
|
|
|
67
99
|
}
|
|
68
100
|
|
|
69
101
|
/**
|
|
70
|
-
* Dispose on close (e.g.
|
|
71
|
-
*
|
|
72
|
-
* next `xtralab:walkthrough` call recreates the panel in the side area.
|
|
102
|
+
* Dispose on close (e.g. after a drag to the main area) instead of leaving a
|
|
103
|
+
* detached widget; the next `xtralab:walkthrough` call recreates the panel.
|
|
73
104
|
*/
|
|
74
105
|
protected onCloseRequest(msg: Message): void {
|
|
75
106
|
super.onCloseRequest(msg);
|
|
@@ -103,7 +134,6 @@ export class WalkthroughPanel extends Panel {
|
|
|
103
134
|
card.addWidget(this._jumpButton(step.path, step.line, step.endLine));
|
|
104
135
|
}
|
|
105
136
|
|
|
106
|
-
// Bring the newest step into view.
|
|
107
137
|
this.node.scrollTop = this.node.scrollHeight;
|
|
108
138
|
}
|
|
109
139
|
|
package/style/about.css
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
/*
|
|
2
|
-
*
|
|
3
|
-
* inherits the jp-Dialog-header type (size2/600 under chrome.css) — the
|
|
4
|
-
* wordmark scales up from there and the version line drops back to body
|
|
5
|
-
* size, weight and a muted color.
|
|
6
|
-
*/
|
|
7
|
-
|
|
1
|
+
/* The header block is the dialog title, so it inherits the jp-Dialog-header
|
|
2
|
+
* type (size2/600 under chrome.css). */
|
|
8
3
|
.jp-xtralab-About-header {
|
|
9
4
|
display: flex;
|
|
10
5
|
align-items: center;
|