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/terminals/index.js
CHANGED
|
@@ -12,41 +12,6 @@ import { SessionRegistry } from './model';
|
|
|
12
12
|
import { IAgentTerminals } from './tokens';
|
|
13
13
|
import { RunningTerminals } from './widget';
|
|
14
14
|
const PLUGIN_ID = 'xtralab:terminals';
|
|
15
|
-
/**
|
|
16
|
-
* Adds a left-sidebar panel that lists every running terminal session.
|
|
17
|
-
*
|
|
18
|
-
* Each row is labelled with the *real* title the running program
|
|
19
|
-
* published — the launcher's agent name, or whatever title an xterm
|
|
20
|
-
* escape sequence set — which the registry caches so it survives the
|
|
21
|
-
* user closing the tab while the session keeps running on the server.
|
|
22
|
-
* JupyterLab's built-in "Running Terminals and Kernels" panel lists the
|
|
23
|
-
* same sessions but only by their `terminals/<n>` name, so this panel
|
|
24
|
-
* resolves and caches the published title to show something meaningful.
|
|
25
|
-
* Rows running a coding agent carry a smaller second line below the
|
|
26
|
-
* title with the agent's latest line of output, so the panel shows what
|
|
27
|
-
* each agent is doing at a glance — on by default, and switchable off
|
|
28
|
-
* through the `showAgentActivity` setting.
|
|
29
|
-
*
|
|
30
|
-
* Clicking a row activates the existing tab if one is open, or reopens
|
|
31
|
-
* the session in a fresh terminal widget (`terminal:open`). The inline
|
|
32
|
-
* `×` button shuts the session down on the server. The Terminals
|
|
33
|
-
* section's title toolbar carries a `+` button and a stop button (the
|
|
34
|
-
* latter shuts every session down at once, after a confirmation).
|
|
35
|
-
*
|
|
36
|
-
* The list is one movable section, and other panels' sections can move in.
|
|
37
|
-
*
|
|
38
|
-
* The `+` button drops down a menu — built from the launcher's shared
|
|
39
|
-
* `IAgentRegistry` — listing each available agent (Claude, Codex, …)
|
|
40
|
-
* followed by a plain terminal, so starting an agent session is as
|
|
41
|
-
* consistent here as in the launcher and reuses the very same registered
|
|
42
|
-
* commands and icons. When the launcher is disabled or no agents are
|
|
43
|
-
* installed, the button falls back to opening a plain terminal directly.
|
|
44
|
-
*
|
|
45
|
-
* The plugin also provides {@link IAgentTerminals} — the sessions with a
|
|
46
|
-
* detection-confirmed running agent, plus a "paste a prompt into one"
|
|
47
|
-
* action — which the ask-agent popup uses to offer running agents as
|
|
48
|
-
* targets next to "new terminal".
|
|
49
|
-
*/
|
|
50
15
|
const plugin = {
|
|
51
16
|
id: PLUGIN_ID,
|
|
52
17
|
description: 'A left-sidebar panel listing every running terminal session by its real (program-published) title, with activate/reopen, shutdown and new-terminal actions.',
|
|
@@ -64,13 +29,8 @@ const plugin = {
|
|
|
64
29
|
],
|
|
65
30
|
activate: (app, tracker, restorer, translator, agentRegistry, editorRegistry, agentSessions, settingRegistry, movableSections) => {
|
|
66
31
|
const trans = (translator !== null && translator !== void 0 ? translator : nullTranslator).load('jupyterlab');
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
// terminal icon when nothing recognised is running. Detection reports
|
|
70
|
-
// either the configured `command` or the canonical `id` (see
|
|
71
|
-
// `detectCommands`), so a row whose command is an alias — e.g. `ccm` for
|
|
72
|
-
// `claude` — still resolves to the right logo via its id. Reads the
|
|
73
|
-
// registries live so it tracks settings changes. Used to badge each row.
|
|
32
|
+
// Detection reports either the configured `command` or the canonical `id`,
|
|
33
|
+
// so an aliased command (e.g. `ccm` for `claude`) still maps to its logo.
|
|
74
34
|
const iconForCommand = (command) => {
|
|
75
35
|
var _a;
|
|
76
36
|
if (!command) {
|
|
@@ -80,18 +40,9 @@ const plugin = {
|
|
|
80
40
|
if (agent) {
|
|
81
41
|
return agent.icon;
|
|
82
42
|
}
|
|
83
|
-
// A terminal running an editor (Neovim/Vim, or a user-configured one) is
|
|
84
|
-
// badged with its logo, the same as an agent.
|
|
85
43
|
const editor = editorRegistry === null || editorRegistry === void 0 ? void 0 : editorRegistry.editors.find(e => e.command === command || e.id === command);
|
|
86
44
|
return (_a = editor === null || editor === void 0 ? void 0 : editor.icon) !== null && _a !== void 0 ? _a : terminalIcon;
|
|
87
45
|
};
|
|
88
|
-
// The names the server should look for in each terminal's process tree:
|
|
89
|
-
// for every agent and editor, its configured `command` plus its canonical
|
|
90
|
-
// `id`. The id is the real CLI name (e.g. `claude`, `nvim`), so an agent
|
|
91
|
-
// whose command points at an alias — e.g. `ccm` running `claude` — is
|
|
92
|
-
// still recognised by the process it actually spawns. Read live so the
|
|
93
|
-
// list tracks settings changes; deduplicated since command and id usually
|
|
94
|
-
// coincide.
|
|
95
46
|
const detectCommands = () => {
|
|
96
47
|
var _a, _b;
|
|
97
48
|
const names = new Set();
|
|
@@ -105,10 +56,6 @@ const plugin = {
|
|
|
105
56
|
}
|
|
106
57
|
return Array.from(names);
|
|
107
58
|
};
|
|
108
|
-
// Whether a detected command/id belongs to a coding agent rather than an
|
|
109
|
-
// editor. Only agent sessions get a latest-activity line (editor
|
|
110
|
-
// terminals stay badge-only), and only they are offered as prompt
|
|
111
|
-
// targets through `IAgentTerminals`.
|
|
112
59
|
const isAgentCommand = (command) => {
|
|
113
60
|
var _a;
|
|
114
61
|
return (_a = agentRegistry === null || agentRegistry === void 0 ? void 0 : agentRegistry.agents.some(a => a.command === command || a.id === command)) !== null && _a !== void 0 ? _a : false;
|
|
@@ -116,18 +63,13 @@ const plugin = {
|
|
|
116
63
|
const registry = new SessionRegistry({
|
|
117
64
|
serviceManager: app.serviceManager,
|
|
118
65
|
tracker,
|
|
119
|
-
// The shell tells the registry which widget is current, so the panel can
|
|
120
|
-
// highlight the terminal that is the current main-area widget (and
|
|
121
|
-
// nothing while a notebook or other widget is current instead).
|
|
122
66
|
shell: app.shell,
|
|
123
67
|
agentSessions,
|
|
124
68
|
detectCommands,
|
|
125
69
|
isAgentCommand
|
|
126
70
|
});
|
|
127
|
-
//
|
|
128
|
-
//
|
|
129
|
-
// `stateChanged` is safe: `Title.icon` ignores an unchanged assignment, so
|
|
130
|
-
// the writes neither loop nor churn.
|
|
71
|
+
// `Title.icon` ignores an unchanged assignment, so re-running per
|
|
72
|
+
// stateChanged is cheap.
|
|
131
73
|
const syncTabIcons = () => {
|
|
132
74
|
tracker.forEach(widget => {
|
|
133
75
|
const session = widget.content.session;
|
|
@@ -140,10 +82,8 @@ const plugin = {
|
|
|
140
82
|
registry.stateChanged.connect(syncTabIcons);
|
|
141
83
|
syncTabIcons();
|
|
142
84
|
const onActivate = (name) => {
|
|
143
|
-
// `terminal:open`
|
|
144
|
-
//
|
|
145
|
-
// session it activates that tab, otherwise it spins up a fresh
|
|
146
|
-
// widget connected to the live session.
|
|
85
|
+
// `terminal:open` activates an attached tab or spins up a fresh widget
|
|
86
|
+
// connected to the live session.
|
|
147
87
|
void app.commands.execute('terminal:open', { name });
|
|
148
88
|
};
|
|
149
89
|
const onShutdown = (name) => {
|
|
@@ -152,10 +92,6 @@ const plugin = {
|
|
|
152
92
|
});
|
|
153
93
|
};
|
|
154
94
|
const onShutdownAll = () => {
|
|
155
|
-
// Tearing down every session at once is hard to undo (each may be a
|
|
156
|
-
// running agent), so confirm before calling the manager's bulk
|
|
157
|
-
// shutdown. `runningChanged` then clears the list and the panel
|
|
158
|
-
// re-renders empty.
|
|
159
95
|
void showDialog({
|
|
160
96
|
title: trans.__('Shut Down All Terminals?'),
|
|
161
97
|
body: trans.__('Are you sure you want to permanently shut down all running terminals?'),
|
|
@@ -173,19 +109,8 @@ const plugin = {
|
|
|
173
109
|
console.error(`xtralab: failed to shut down all terminals: ${reason}`);
|
|
174
110
|
});
|
|
175
111
|
};
|
|
176
|
-
//
|
|
177
|
-
//
|
|
178
|
-
// `xtralab:start-agent:<id>` commands, so the icons and labels match the
|
|
179
|
-
// launcher exactly) followed by a separator and a plain terminal. Built
|
|
180
|
-
// lazily and repopulated on each open so it always reflects the current,
|
|
181
|
-
// settings-driven agent list. Without the registry (launcher disabled)
|
|
182
|
-
// or with no agents installed, there is nothing to choose between, so
|
|
183
|
-
// the button opens a plain terminal directly in one click.
|
|
184
|
-
//
|
|
185
|
-
// `MenuSvg` (not the bare Lumino `Menu`) is what every JupyterLab menu
|
|
186
|
-
// uses: its renderer applies the `menuItem` LabIcon stylesheet, which
|
|
187
|
-
// sizes the agent icons to 16px and centers them vertically — the bare
|
|
188
|
-
// `Menu` renders the raw, oversized, misaligned SVGs.
|
|
112
|
+
// `MenuSvg`, not the bare Lumino `Menu`: its renderer applies the `menuItem`
|
|
113
|
+
// LabIcon stylesheet — the bare menu renders raw, oversized SVGs.
|
|
189
114
|
let newMenu = null;
|
|
190
115
|
const onCreate = (anchor) => {
|
|
191
116
|
var _a;
|
|
@@ -214,15 +139,8 @@ const plugin = {
|
|
|
214
139
|
onShutdownAll,
|
|
215
140
|
onCreate
|
|
216
141
|
});
|
|
217
|
-
//
|
|
218
|
-
//
|
|
219
|
-
// this Terminals panel ranks first, so running agents sit one click
|
|
220
|
-
// away at the top. That setting assigns rank only and pins no area, so
|
|
221
|
-
// the "Move Widget" context menu can relocate the panel and the layout
|
|
222
|
-
// restorer remembers where the user puts it. The `rank` here is the
|
|
223
|
-
// in-code fallback used when the setting is absent. Sessions restored
|
|
224
|
-
// from a previous lab run land via `runningChanged` once the terminal
|
|
225
|
-
// manager is ready, which the panel's `UseSignal` picks up.
|
|
142
|
+
// The shipped labconfig `layout` setting ranks this panel first (rank only,
|
|
143
|
+
// no area pin, so "Move Widget" works); this rank is the fallback.
|
|
226
144
|
app.shell.add(panel, 'left', { rank: 1 });
|
|
227
145
|
if (restorer) {
|
|
228
146
|
restorer.add(panel, panel.id);
|
|
@@ -235,9 +153,6 @@ const plugin = {
|
|
|
235
153
|
movableSections.registerTarget(PLUGIN_ID, trans.__('Terminals'), panel);
|
|
236
154
|
panel.announceSections();
|
|
237
155
|
}
|
|
238
|
-
// The latest-activity line under each agent row is on by default; honour
|
|
239
|
-
// the `showAgentActivity` setting so it can be turned off. Read on load and
|
|
240
|
-
// re-applied on every change.
|
|
241
156
|
if (settingRegistry) {
|
|
242
157
|
settingRegistry
|
|
243
158
|
.load(PLUGIN_ID)
|
|
@@ -246,9 +161,8 @@ const plugin = {
|
|
|
246
161
|
registry.setActivityEnabled(boolOption(settings.composite.showAgentActivity, true));
|
|
247
162
|
};
|
|
248
163
|
applyActivitySetting();
|
|
249
|
-
//
|
|
250
|
-
//
|
|
251
|
-
// then never reached on a later settings change.
|
|
164
|
+
// Bound to the panel so disposing it drops the connection — the
|
|
165
|
+
// disposed registry is never reached on a later settings change.
|
|
252
166
|
settings.changed.connect(applyActivitySetting, panel);
|
|
253
167
|
})
|
|
254
168
|
.catch(reason => {
|
|
@@ -265,9 +179,6 @@ const plugin = {
|
|
|
265
179
|
});
|
|
266
180
|
}
|
|
267
181
|
};
|
|
268
|
-
/**
|
|
269
|
-
* Read a boolean setting value, falling back when it is missing or invalid.
|
|
270
|
-
*/
|
|
271
182
|
function boolOption(value, fallback) {
|
|
272
183
|
return typeof value === 'boolean' ? value : fallback;
|
|
273
184
|
}
|
package/lib/terminals/model.d.ts
CHANGED
|
@@ -5,191 +5,114 @@ import type { ITerminal, ITerminalTracker } from '@jupyterlab/terminal';
|
|
|
5
5
|
import type { IDisposable } from '@lumino/disposable';
|
|
6
6
|
import { ISignal } from '@lumino/signaling';
|
|
7
7
|
import type { IAgentSessions } from '../agentSessions';
|
|
8
|
-
/**
|
|
9
|
-
* The widget shape every entry in `ITerminalTracker` takes — kept here
|
|
10
|
-
* so the registry's call sites read cleanly.
|
|
11
|
-
*/
|
|
12
8
|
export type TerminalWidget = MainAreaWidget<ITerminal.ITerminal>;
|
|
13
9
|
/**
|
|
14
|
-
* Source-of-truth model for the running-terminals panel
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* session continues running on the backend.
|
|
19
|
-
*
|
|
20
|
-
* For sessions running a coding agent it also surfaces a *latest activity*
|
|
21
|
-
* line — the freshest meaningful line of the terminal's output, read from the
|
|
22
|
-
* open tab's xterm buffer on a poll (see {@link activityFor}) — so each row
|
|
23
|
-
* shows what its agent is doing, not just its name.
|
|
24
|
-
*
|
|
25
|
-
* It also resolves *which agent is running* in each session, so the panel can
|
|
26
|
-
* badge rows with the agent's logo. Two inputs feed that, reconciled by
|
|
27
|
-
* {@link agentCommandFor}:
|
|
28
|
-
* - an optimistic launch tag ({@link IAgentSessions}) written when we start
|
|
29
|
-
* an agent ourselves — instant, but blind to the agent later exiting; and
|
|
30
|
-
* - authoritative server-side process detection, polled here, which works
|
|
31
|
-
* for hand-started agents too and clears once an agent exits.
|
|
32
|
-
*
|
|
33
|
-
* Upstream session signals:
|
|
34
|
-
* - `serviceManager.terminals.runningChanged` is the authoritative
|
|
35
|
-
* list of live sessions; everything not in it has been shut down
|
|
36
|
-
* server-side and we must drop it.
|
|
37
|
-
* - `tracker.widgetAdded` plus the per-widget `title.changed` /
|
|
38
|
-
* `disposed` signals keep our label cache in sync with whatever
|
|
39
|
-
* xterm/the launcher has set on the open tabs.
|
|
40
|
-
*
|
|
41
|
-
* `stateChanged` is emitted for every kind of update; the panel hooks it
|
|
42
|
-
* through a `UseSignal` so a single subscription re-renders the list on
|
|
43
|
-
* any change.
|
|
10
|
+
* Source-of-truth model for the running-terminals panel: live sessions,
|
|
11
|
+
* labels cached across tab closes, agent badges (launch tags reconciled with
|
|
12
|
+
* polled detection, see {@link agentCommandFor}), and per-row latest-activity
|
|
13
|
+
* lines. `stateChanged` fires on every kind of update.
|
|
44
14
|
*/
|
|
45
15
|
export declare class SessionRegistry implements IDisposable {
|
|
46
16
|
constructor(options: SessionRegistry.IOptions);
|
|
47
17
|
/**
|
|
48
|
-
* Emitted
|
|
49
|
-
* running agent changes.
|
|
18
|
+
* Emitted on any change to the session list, labels, badges, or activity.
|
|
50
19
|
*/
|
|
51
20
|
get stateChanged(): ISignal<this, void>;
|
|
21
|
+
/**
|
|
22
|
+
* Whether the registry has been disposed.
|
|
23
|
+
*/
|
|
52
24
|
get isDisposed(): boolean;
|
|
53
25
|
/**
|
|
54
|
-
* Names of all live sessions
|
|
55
|
-
* rendered list keeps a consistent order (roughly creation order) as
|
|
56
|
-
* new sessions are added and old ones shut down.
|
|
26
|
+
* Names of all live sessions in stable (roughly creation) order.
|
|
57
27
|
*/
|
|
58
28
|
sessionNames(): string[];
|
|
59
29
|
/**
|
|
60
|
-
* True iff the named session is still on the server.
|
|
61
|
-
* to skip a row during the brief window between the session's shutdown
|
|
62
|
-
* and the next `runningChanged` arriving.
|
|
30
|
+
* True iff the named session is still on the server.
|
|
63
31
|
*/
|
|
64
32
|
has(name: string): boolean;
|
|
65
33
|
/**
|
|
66
|
-
* Display name for the session. The cache wins
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* during reconnect from flickering into the panel. The live widget
|
|
71
|
-
* title is used when no cache exists, and the `Terminal {name}`
|
|
72
|
-
* fallback covers sessions we have never seen a widget for (e.g.
|
|
73
|
-
* surviving a lab reload).
|
|
34
|
+
* Display name for the session. The cache wins — it holds only "real"
|
|
35
|
+
* labels (see `_cacheLabel`), so the transient `Terminal {name}` an xterm
|
|
36
|
+
* widget shows during reconnect never flickers into the panel; the final
|
|
37
|
+
* fallback covers sessions never seen with a widget (e.g. a lab reload).
|
|
74
38
|
*/
|
|
75
39
|
labelFor(name: string): string;
|
|
76
40
|
/**
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* Server-side detection is authoritative whenever it reports a running
|
|
83
|
-
* agent. A launch tag fills two gaps: the startup grace window right after
|
|
84
|
-
* we launch an agent (so its logo shows before its process is detectable),
|
|
85
|
-
* and any time detection is unavailable (older server, transient error).
|
|
86
|
-
* Once the grace window has passed and detection has reported the session
|
|
87
|
-
* as idle, the tag is ignored — that is how the badge clears when an agent
|
|
88
|
-
* exits.
|
|
41
|
+
* Agent identifier for the session (configured command or canonical id), or
|
|
42
|
+
* `null`. Detection wins when it reports an agent; a launch tag fills the
|
|
43
|
+
* grace window and detection outages, and is ignored once detection says
|
|
44
|
+
* idle — that is how the badge clears when an agent exits.
|
|
89
45
|
*/
|
|
90
46
|
agentCommandFor(name: string): string | null;
|
|
91
47
|
/**
|
|
92
|
-
* The agent command
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* {@link agentCommandFor} this never falls back to the optimistic launch
|
|
96
|
-
* tags: callers about to *write into* a session use it, and text must only
|
|
97
|
-
* ever be sent to a confirmed running agent — pasted into a shell prompt it
|
|
98
|
-
* would be executed.
|
|
48
|
+
* The agent command detection currently confirms for the session, or
|
|
49
|
+
* `null`. Never falls back to launch tags: callers about to *write into* a
|
|
50
|
+
* session use it, and text pasted into a shell prompt would be executed.
|
|
99
51
|
*/
|
|
100
52
|
detectedCommandFor(name: string): string | null;
|
|
101
53
|
/**
|
|
102
|
-
* The most recent meaningful line of
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
* buffer holds only the agent's input box and chrome. Refreshed on a poll by
|
|
106
|
-
* {@link _refreshActivity}; shown as a smaller line under the row's title.
|
|
107
|
-
* Always `null` while the activity line is disabled (see
|
|
108
|
-
* {@link setActivityEnabled}).
|
|
54
|
+
* The most recent meaningful line of the session's output, or `null` when
|
|
55
|
+
* nothing qualifies (no running agent, closed tab, chrome-only buffer, or
|
|
56
|
+
* the activity line is disabled).
|
|
109
57
|
*/
|
|
110
58
|
activityFor(name: string): string | null;
|
|
111
59
|
/**
|
|
112
|
-
* Turn the per-row
|
|
113
|
-
*
|
|
114
|
-
* activity poll stops reading terminal buffers and any cached lines are
|
|
115
|
-
* dropped, so rows fall back to their title alone; when turned back on the
|
|
116
|
-
* lines are repopulated on the spot. A no-op when the value is unchanged.
|
|
60
|
+
* Turn the per-row activity line on or off (the `showAgentActivity`
|
|
61
|
+
* setting). Off drops cached lines; on repopulates them on the spot.
|
|
117
62
|
*/
|
|
118
63
|
setActivityEnabled(enabled: boolean): void;
|
|
119
64
|
/**
|
|
120
|
-
*
|
|
121
|
-
* switch behavior between "activate existing tab" and "open a new tab
|
|
122
|
-
* connected to the live session".
|
|
65
|
+
* The open widget for a session, if any.
|
|
123
66
|
*/
|
|
124
67
|
widgetFor(name: string): TerminalWidget | null;
|
|
125
68
|
/**
|
|
126
|
-
* Session name of the terminal that is
|
|
127
|
-
*
|
|
128
|
-
* example a notebook or text editor is current). The panel uses this to
|
|
129
|
-
* highlight the current terminal's row — mirroring how the file browser
|
|
130
|
-
* surfaces the open document — and to leave every row unhighlighted while a
|
|
131
|
-
* non-terminal tab is current.
|
|
69
|
+
* Session name of the terminal that is the shell's current main-area
|
|
70
|
+
* widget, or `null` when the current widget is not a terminal.
|
|
132
71
|
*/
|
|
133
72
|
currentSessionName(): string | null;
|
|
134
73
|
/**
|
|
135
|
-
* Stable per-session rank
|
|
136
|
-
*
|
|
137
|
-
* sessions come and go. Cleaned up when the session is shut down so the
|
|
138
|
-
* counter does not grow without bound across long sessions.
|
|
74
|
+
* Stable per-session rank in observation order, so rows don't reshuffle as
|
|
75
|
+
* sessions come and go.
|
|
139
76
|
*/
|
|
140
77
|
rankFor(name: string): number;
|
|
78
|
+
/**
|
|
79
|
+
* Dispose of the registry's polls and signal connections.
|
|
80
|
+
*/
|
|
141
81
|
dispose(): void;
|
|
142
82
|
private _refreshLive;
|
|
143
83
|
private _onRunningChanged;
|
|
144
84
|
/**
|
|
145
|
-
* Adopt `next` as the live set and prune every per-session map
|
|
146
|
-
*
|
|
147
|
-
* detection results, and the shared launch tag. Without this the maps (and
|
|
148
|
-
* the rank counter) would grow without bound as terminals come and go.
|
|
85
|
+
* Adopt `next` as the live set and prune every per-session map, so the
|
|
86
|
+
* maps and rank counter don't grow without bound.
|
|
149
87
|
*/
|
|
150
88
|
private _reconcileLive;
|
|
151
89
|
/**
|
|
152
|
-
* Poll body:
|
|
153
|
-
*
|
|
154
|
-
* clearing them, so a transient error doesn't strip every badge.
|
|
90
|
+
* Poll body: update the detection map from the server. On failure the
|
|
91
|
+
* previous results are kept, so a transient error doesn't strip every badge.
|
|
155
92
|
*/
|
|
156
93
|
private _refreshDetection;
|
|
157
94
|
/**
|
|
158
|
-
* Poll body:
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
* buffer, editors run full-screen UIs that are not "activity", and plain
|
|
162
|
-
* shells would only echo their prompt. While a tab is reopening (its xterm
|
|
163
|
-
* is not ready yet) any existing line is kept; once the buffer is readable
|
|
164
|
-
* but has nothing worth showing the line is dropped, so a screen the agent
|
|
165
|
-
* has cleared doesn't leave a frozen line behind. Cached lines for sessions
|
|
166
|
-
* that no longer qualify are pruned. Emits only when something changed.
|
|
95
|
+
* Poll body: cache the latest meaningful output line of each open agent
|
|
96
|
+
* terminal (closed tabs have no live buffer; editors and shells don't
|
|
97
|
+
* qualify). Emits only when something changed.
|
|
167
98
|
*/
|
|
168
99
|
private _refreshActivity;
|
|
169
100
|
private _onTagChanged;
|
|
170
101
|
private _onWidgetAdded;
|
|
171
102
|
private _onShellCurrentChanged;
|
|
172
103
|
/**
|
|
173
|
-
* Recompute which terminal (if any) is the active main-area widget
|
|
174
|
-
* only
|
|
175
|
-
* current widget is one of our terminals; anything else — a notebook, an
|
|
176
|
-
* editor, or nothing — clears the highlight.
|
|
104
|
+
* Recompute which terminal (if any) is the active main-area widget; emits
|
|
105
|
+
* only on change. Anything not a tracked terminal clears the highlight.
|
|
177
106
|
*/
|
|
178
107
|
private _updateCurrent;
|
|
179
108
|
private _trackWidget;
|
|
180
109
|
private _untrackWidget;
|
|
181
110
|
private _onTitleChanged;
|
|
182
111
|
/**
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
* the
|
|
187
|
-
* `_initialConnection` fires). Without the filter, briefly
|
|
188
|
-
* reopening a tab while an agent has yet to re-emit its xterm
|
|
189
|
-
* title escape sequence would clobber the cached agent name with
|
|
190
|
-
* `Terminal 1`. Live widget titles still display whatever the widget
|
|
191
|
-
* currently holds because `labelFor` consults the widget first;
|
|
192
|
-
* the filter only affects what survives a tab close.
|
|
112
|
+
* Cache a label only when it is "real" — not `'...'` or `Terminal {name}`,
|
|
113
|
+
* the transient defaults xterm cycles through during reconnect. Without the
|
|
114
|
+
* filter, reopening a tab before the agent re-emits its title escape would
|
|
115
|
+
* clobber the cached agent name.
|
|
193
116
|
*/
|
|
194
117
|
private _cacheLabel;
|
|
195
118
|
private _onWidgetDisposed;
|
|
@@ -217,15 +140,21 @@ export declare class SessionRegistry implements IDisposable {
|
|
|
217
140
|
* Construction options for {@link SessionRegistry}.
|
|
218
141
|
*/
|
|
219
142
|
export declare namespace SessionRegistry {
|
|
143
|
+
/**
|
|
144
|
+
* The instantiation options for a session registry.
|
|
145
|
+
*/
|
|
220
146
|
interface IOptions {
|
|
147
|
+
/**
|
|
148
|
+
* The service manager whose terminal manager supplies the sessions.
|
|
149
|
+
*/
|
|
221
150
|
serviceManager: ServiceManager.IManager;
|
|
151
|
+
/**
|
|
152
|
+
* The tracker of open terminal widgets.
|
|
153
|
+
*/
|
|
222
154
|
tracker: ITerminalTracker;
|
|
223
155
|
/**
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
* widget — and highlight nothing when that widget is not a terminal (a
|
|
227
|
-
* notebook, an editor, …). Optional: without it, or on a shell that cannot
|
|
228
|
-
* report `currentChanged`, the highlight stays off.
|
|
156
|
+
* Used to highlight the row of the current main-area terminal. Optional:
|
|
157
|
+
* without it (or its `currentChanged`) the highlight stays off.
|
|
229
158
|
*/
|
|
230
159
|
shell?: JupyterFrontEnd.IShell | null;
|
|
231
160
|
/**
|
|
@@ -234,19 +163,15 @@ export declare namespace SessionRegistry {
|
|
|
234
163
|
*/
|
|
235
164
|
agentSessions?: IAgentSessions | null;
|
|
236
165
|
/**
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
* matched by the process it spawns. Read on every poll so it tracks the
|
|
241
|
-
* live agent list.
|
|
166
|
+
* Names to detect: each agent's command plus its canonical id, so an
|
|
167
|
+
* aliased command (e.g. `ccm` running `claude`) is still matched by the
|
|
168
|
+
* process it spawns. Read on every poll.
|
|
242
169
|
*/
|
|
243
170
|
detectCommands?: () => string[];
|
|
244
171
|
/**
|
|
245
|
-
* Whether a detected command (or id) belongs to a coding agent rather
|
|
246
|
-
* an editor
|
|
247
|
-
*
|
|
248
|
-
* meaningfully "activity". Defaults to treating every detected command as an
|
|
249
|
-
* agent.
|
|
172
|
+
* Whether a detected command (or id) belongs to a coding agent rather
|
|
173
|
+
* than an editor; only agent sessions get a latest-activity line.
|
|
174
|
+
* Defaults to treating every detected command as an agent.
|
|
250
175
|
*/
|
|
251
176
|
isAgentCommand?: (command: string) => boolean;
|
|
252
177
|
}
|