xtralab 0.14.1 → 0.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -0
- 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.d.ts +7 -0
- package/lib/customPanel/index.js +89 -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 +28 -19
- package/lib/fileBrowser/commands.js +51 -98
- package/lib/fileBrowser/contents.d.ts +14 -0
- package/lib/fileBrowser/contents.js +28 -0
- package/lib/fileBrowser/dragAndDrop.d.ts +79 -0
- package/lib/fileBrowser/dragAndDrop.js +110 -0
- package/lib/fileBrowser/fileBrowser.d.ts +21 -9
- package/lib/fileBrowser/fileBrowser.js +211 -405
- package/lib/fileBrowser/gitStatus.d.ts +4 -9
- package/lib/fileBrowser/gitStatus.js +7 -17
- 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 +41 -10
- package/lib/fileBrowser/widget.d.ts +170 -53
- package/lib/fileBrowser/widget.js +242 -18
- 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 +40 -5
- package/lib/git/commands.js +16 -10
- package/lib/git/diffModel.js +4 -0
- package/lib/git/diffSurface.d.ts +41 -55
- package/lib/git/diffSurface.js +42 -117
- package/lib/git/diffWidget.d.ts +81 -2
- package/lib/git/diffWidget.js +62 -12
- package/lib/git/imageDiff.d.ts +5 -6
- package/lib/git/imageDiff.js +18 -48
- package/lib/git/index.d.ts +0 -3
- package/lib/git/index.js +3 -8
- package/lib/git/notebookDiff.d.ts +110 -33
- package/lib/git/notebookDiff.js +52 -195
- 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 +2 -9
- package/lib/launcher/agents.d.ts +55 -51
- package/lib/launcher/agents.js +25 -54
- 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 +14 -37
- 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/schemaDefaults.d.ts +2 -9
- package/lib/launcher/schemaDefaults.js +37 -13
- 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 -13
- package/lib/sidebar/index.js +73 -46
- 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 -33
- package/lib/terminals/index.js +24 -102
- 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 +72 -38
- package/lib/terminals/widget.js +173 -73
- 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 +2 -2
- package/schema/launcher.json +2 -2
- package/schema/sidebar.json +47 -7
- 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 +119 -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 +70 -98
- package/src/fileBrowser/contents.ts +33 -0
- package/src/fileBrowser/dragAndDrop.ts +188 -0
- package/src/fileBrowser/fileBrowser.tsx +259 -440
- package/src/fileBrowser/gitStatus.ts +7 -17
- package/src/fileBrowser/gitignore.ts +4 -25
- package/src/fileBrowser/icons.ts +25 -80
- package/src/fileBrowser/index.ts +43 -10
- package/src/fileBrowser/widget.tsx +344 -64
- 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 +70 -10
- package/src/git/diffModel.ts +25 -0
- package/src/git/diffSurface.tsx +71 -159
- package/src/git/diffWidget.tsx +104 -14
- package/src/git/imageDiff.tsx +45 -51
- package/src/git/index.ts +3 -8
- package/src/git/notebookDiff.tsx +211 -238
- package/src/git/tokens.ts +73 -31
- package/src/highlight/index.ts +10 -41
- package/src/index.ts +2 -9
- package/src/launcher/agents.ts +74 -92
- 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 +15 -37
- package/src/launcher/index.ts +12 -55
- package/src/launcher/invocation.ts +7 -22
- package/src/launcher/registry.ts +9 -7
- package/src/launcher/schemaDefaults.ts +43 -13
- 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 +103 -52
- 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 +31 -102
- package/src/terminals/model.ts +130 -246
- package/src/terminals/tokens.ts +11 -22
- package/src/terminals/widget.tsx +229 -113
- 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 +25 -73
- package/style/chrome.css +108 -308
- package/style/commandBar.css +4 -20
- package/style/customPanel.css +6 -0
- package/style/git.css +22 -184
- package/style/highlight.css +1 -3
- package/style/index.js +1 -0
- 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 +18 -123
- package/style/topBar.css +2 -22
- package/style/walkthrough.css +0 -8
package/lib/omnibox/recents.js
CHANGED
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Identity of an entry: two uses only match when kind, id and args all do,
|
|
3
|
-
*
|
|
2
|
+
* Identity of an entry: two uses only match when kind, id and args all do, so
|
|
3
|
+
* runs of one command with different args stay distinct.
|
|
4
4
|
*/
|
|
5
5
|
function entryKey(entry) {
|
|
6
6
|
var _a;
|
|
7
7
|
return `${entry.kind}\0${entry.id}\0${JSON.stringify((_a = entry.args) !== null && _a !== void 0 ? _a : null)}`;
|
|
8
8
|
}
|
|
9
|
-
/**
|
|
10
|
-
* State database key the recents list is persisted under.
|
|
11
|
-
*/
|
|
12
9
|
const STATE_KEY = 'xtralab:omnibox:recents';
|
|
13
10
|
/**
|
|
14
|
-
* A most-recently-used list of omnibox results,
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* state database so they survive reloads. Without a state database the list
|
|
18
|
-
* still works for the lifetime of the page.
|
|
11
|
+
* A most-recently-used list of omnibox results, most-recent-first, capped at
|
|
12
|
+
* `maxItems` per kind and persisted through the state database. Without a
|
|
13
|
+
* state database it still works for the lifetime of the page.
|
|
19
14
|
*/
|
|
20
15
|
export class OmniboxRecents {
|
|
21
16
|
constructor(options = {}) {
|
|
@@ -25,12 +20,14 @@ export class OmniboxRecents {
|
|
|
25
20
|
this._state = (_a = options.state) !== null && _a !== void 0 ? _a : null;
|
|
26
21
|
}
|
|
27
22
|
/**
|
|
28
|
-
* Maximum
|
|
29
|
-
* immediately; `0` disables recents entirely.
|
|
23
|
+
* Maximum entries kept per kind; lowering trims immediately, `0` disables recents.
|
|
30
24
|
*/
|
|
31
25
|
get maxItems() {
|
|
32
26
|
return this._maxItems;
|
|
33
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Set the maximum entries kept per kind.
|
|
30
|
+
*/
|
|
34
31
|
set maxItems(value) {
|
|
35
32
|
const normalized = Math.max(0, Math.floor(value));
|
|
36
33
|
if (normalized === this._maxItems) {
|
|
@@ -44,8 +41,7 @@ export class OmniboxRecents {
|
|
|
44
41
|
}
|
|
45
42
|
}
|
|
46
43
|
/**
|
|
47
|
-
* The recorded entries, most recent first
|
|
48
|
-
* one kind.
|
|
44
|
+
* The recorded entries, most recent first, optionally filtered to one kind.
|
|
49
45
|
*/
|
|
50
46
|
entries(kind) {
|
|
51
47
|
return kind
|
|
@@ -53,8 +49,7 @@ export class OmniboxRecents {
|
|
|
53
49
|
: [...this._entries];
|
|
54
50
|
}
|
|
55
51
|
/**
|
|
56
|
-
* Record a use
|
|
57
|
-
* the front of its kind's list.
|
|
52
|
+
* Record a use, moving the entry to the front of its kind's list.
|
|
58
53
|
*/
|
|
59
54
|
touch(kind, id, args) {
|
|
60
55
|
const entry = args === undefined ? { kind, id } : { kind, id, args };
|
|
@@ -65,7 +60,7 @@ export class OmniboxRecents {
|
|
|
65
60
|
}
|
|
66
61
|
/**
|
|
67
62
|
* Load the persisted list. Entries recorded before the load completes stay
|
|
68
|
-
*
|
|
63
|
+
* ahead of the restored history.
|
|
69
64
|
*/
|
|
70
65
|
async restore() {
|
|
71
66
|
if (!this._state) {
|
package/lib/omnibox/tokens.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { Token } from '@lumino/coreutils';
|
|
2
2
|
/**
|
|
3
|
-
* A launcher overlay that fuzzy-searches
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* by the top-bar command bar, which opens it on click.
|
|
3
|
+
* A launcher overlay that fuzzy-searches workspace files and commands and
|
|
4
|
+
* routes a typed prompt to a configured agent. Provided by `xtralab:omnibox`;
|
|
5
|
+
* opened by the top-bar command bar.
|
|
7
6
|
*/
|
|
8
7
|
export interface IOmnibox {
|
|
9
8
|
/**
|
|
@@ -15,13 +14,9 @@ export interface IOmnibox {
|
|
|
15
14
|
*/
|
|
16
15
|
close(): void;
|
|
17
16
|
}
|
|
18
|
-
/**
|
|
19
|
-
* DI token for {@link IOmnibox}. Provided by `xtralab:omnibox`; consumed by
|
|
20
|
-
* `xtralab:command-bar` so the top-bar pill opens the omnibox.
|
|
21
|
-
*/
|
|
22
17
|
export declare const IOmnibox: Token<IOmnibox>;
|
|
23
18
|
/**
|
|
24
|
-
* Command id that opens the omnibox
|
|
25
|
-
*
|
|
19
|
+
* Command id that opens the omnibox, shared so the command bar can look up
|
|
20
|
+
* its keybinding for the shortcut hint.
|
|
26
21
|
*/
|
|
27
22
|
export declare const OMNIBOX_OPEN_COMMAND = "xtralab:omnibox:open";
|
package/lib/omnibox/tokens.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { Token } from '@lumino/coreutils';
|
|
2
|
-
/**
|
|
3
|
-
* DI token for {@link IOmnibox}. Provided by `xtralab:omnibox`; consumed by
|
|
4
|
-
* `xtralab:command-bar` so the top-bar pill opens the omnibox.
|
|
5
|
-
*/
|
|
6
2
|
export const IOmnibox = new Token('xtralab:IOmnibox', 'Opens the omnibox overlay that searches files and commands and prompts agents.');
|
|
7
3
|
/**
|
|
8
|
-
* Command id that opens the omnibox
|
|
9
|
-
*
|
|
4
|
+
* Command id that opens the omnibox, shared so the command bar can look up
|
|
5
|
+
* its keybinding for the shortcut hint.
|
|
10
6
|
*/
|
|
11
7
|
export const OMNIBOX_OPEN_COMMAND = 'xtralab:omnibox:open';
|
package/lib/omnibox/widget.d.ts
CHANGED
|
@@ -6,30 +6,34 @@ import type { CommandPalette } from '@lumino/widgets';
|
|
|
6
6
|
import type { IAgent } from '../launcher/agents';
|
|
7
7
|
import type { OmniboxRecents } from './recents';
|
|
8
8
|
/**
|
|
9
|
-
* The omnibox overlay widget
|
|
10
|
-
*
|
|
11
|
-
* theme CSS variables resolve outside the shell, and its own `jp-xtralab-Omnibox`
|
|
12
|
-
* class for the overlay/panel styling (style/omnibox.css).
|
|
9
|
+
* The omnibox overlay widget, attached to `document.body`; `jp-ThemedContainer`
|
|
10
|
+
* makes JupyterLab's theme CSS variables resolve outside the shell.
|
|
13
11
|
*/
|
|
14
12
|
export declare class OmniboxWidget extends ReactWidget {
|
|
15
13
|
constructor(options: OmniboxWidget.IOptions);
|
|
14
|
+
/**
|
|
15
|
+
* Render the omnibox overlay content.
|
|
16
|
+
*/
|
|
16
17
|
render(): JSX.Element;
|
|
17
18
|
private _options;
|
|
18
19
|
}
|
|
19
|
-
/**
|
|
20
|
-
* A namespace for `OmniboxWidget` statics.
|
|
21
|
-
*/
|
|
22
20
|
export declare namespace OmniboxWidget {
|
|
23
21
|
/**
|
|
24
22
|
* Construction options for {@link OmniboxWidget}.
|
|
25
23
|
*/
|
|
26
24
|
interface IOptions {
|
|
25
|
+
/**
|
|
26
|
+
* The command registry used to look up and execute commands.
|
|
27
|
+
*/
|
|
27
28
|
commands: CommandRegistry;
|
|
28
29
|
/**
|
|
29
30
|
* Snapshot of the command palette's items, read once when the overlay
|
|
30
31
|
* opens; empty when the palette isn't available.
|
|
31
32
|
*/
|
|
32
33
|
paletteItems: ReadonlyArray<CommandPalette.IItem>;
|
|
34
|
+
/**
|
|
35
|
+
* The document registry used to pick file icons.
|
|
36
|
+
*/
|
|
33
37
|
docRegistry: DocumentRegistry;
|
|
34
38
|
/**
|
|
35
39
|
* Snapshot of the available agents, read once when the overlay opens.
|
package/lib/omnibox/widget.js
CHANGED
|
@@ -2,19 +2,13 @@ import { ReactWidget } from '@jupyterlab/ui-components';
|
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { computeSections } from './model';
|
|
4
4
|
import { loadWorkspaceFiles } from './files';
|
|
5
|
-
/**
|
|
6
|
-
* DOM id of the results listbox, referenced by the input's `aria-controls`.
|
|
7
|
-
*/
|
|
8
5
|
const LIST_ID = 'jp-xtralab-Omnibox-list';
|
|
9
|
-
/**
|
|
10
|
-
* Stable DOM id for the result row at `index`, for `aria-activedescendant`.
|
|
11
|
-
*/
|
|
12
6
|
function optionId(index) {
|
|
13
7
|
return `jp-xtralab-Omnibox-option-${index}`;
|
|
14
8
|
}
|
|
15
9
|
/**
|
|
16
10
|
* Render `text` with the fuzzy-matched characters at `indices` wrapped in a
|
|
17
|
-
* highlight span
|
|
11
|
+
* highlight span.
|
|
18
12
|
*/
|
|
19
13
|
function renderHighlight(text, indices) {
|
|
20
14
|
if (indices.length === 0) {
|
|
@@ -77,19 +71,16 @@ function OmniboxComponent(props) {
|
|
|
77
71
|
...sections.agents
|
|
78
72
|
], [sections]);
|
|
79
73
|
const hasResults = flat.length > 0;
|
|
80
|
-
// Reset the highlighted row whenever the result set changes, and keep the
|
|
81
|
-
// index in range when results shrink.
|
|
82
74
|
React.useEffect(() => {
|
|
83
75
|
setActive(current => (current < flat.length ? current : 0));
|
|
84
76
|
}, [flat]);
|
|
85
|
-
// Keep the highlighted row scrolled into view as it moves.
|
|
86
77
|
React.useEffect(() => {
|
|
87
78
|
var _a, _b;
|
|
88
79
|
(_b = (_a = listRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('.jp-mod-active')) === null || _b === void 0 ? void 0 : _b.scrollIntoView({ block: 'nearest' });
|
|
89
80
|
}, [active, flat]);
|
|
90
81
|
const dismiss = React.useCallback(() => {
|
|
91
|
-
// Defer so unmounting this React root
|
|
92
|
-
//
|
|
82
|
+
// Defer so unmounting this React root never happens synchronously inside
|
|
83
|
+
// the event handler that triggered it.
|
|
93
84
|
window.setTimeout(onClose, 0);
|
|
94
85
|
}, [onClose]);
|
|
95
86
|
const run = React.useCallback((item) => {
|
|
@@ -162,10 +153,8 @@ function OmniboxComponent(props) {
|
|
|
162
153
|
: trans.__('Search files and commands, or type a prompt and pick an agent. Prefix with > for commands or / for files.')))))));
|
|
163
154
|
}
|
|
164
155
|
/**
|
|
165
|
-
* The omnibox overlay widget
|
|
166
|
-
*
|
|
167
|
-
* theme CSS variables resolve outside the shell, and its own `jp-xtralab-Omnibox`
|
|
168
|
-
* class for the overlay/panel styling (style/omnibox.css).
|
|
156
|
+
* The omnibox overlay widget, attached to `document.body`; `jp-ThemedContainer`
|
|
157
|
+
* makes JupyterLab's theme CSS variables resolve outside the shell.
|
|
169
158
|
*/
|
|
170
159
|
export class OmniboxWidget extends ReactWidget {
|
|
171
160
|
constructor(options) {
|
|
@@ -175,6 +164,9 @@ export class OmniboxWidget extends ReactWidget {
|
|
|
175
164
|
this.addClass('jp-xtralab-Omnibox');
|
|
176
165
|
this.addClass('jp-ThemedContainer');
|
|
177
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Render the omnibox overlay content.
|
|
169
|
+
*/
|
|
178
170
|
render() {
|
|
179
171
|
return React.createElement(OmniboxComponent, { ...this._options });
|
|
180
172
|
}
|
|
@@ -1,25 +1,9 @@
|
|
|
1
1
|
import { JupyterFrontEndPlugin } from '@jupyterlab/application';
|
|
2
2
|
/**
|
|
3
|
-
* Bind Accel+Shift+F
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* Two pieces are needed because that chord is already taken: JupyterLab core
|
|
8
|
-
* binds Accel+Shift+F to `filebrowser:toggle-main`.
|
|
9
|
-
*
|
|
10
|
-
* 1. The chord is freed declaratively. `SettingRegistry.reconcileShortcuts`
|
|
11
|
-
* keys collisions and disables on (keys, selector) — not on command — so the
|
|
12
|
-
* `@jupyterlab/shortcuts-extension:shortcuts` override in
|
|
13
|
-
* `default_setting_overrides.d/00-xtralab.json` disables the file-browser
|
|
14
|
-
* binding. The file browser stays reachable from its sidebar tab and the
|
|
15
|
-
* View menu; only the keyboard shortcut moves.
|
|
16
|
-
*
|
|
17
|
-
* 2. The new binding is added imperatively below rather than as another shipped
|
|
18
|
-
* default. A `disabled` default and a re-binding default land on the same
|
|
19
|
-
* (keys, selector) slot, and the disable suppresses every default on that
|
|
20
|
-
* slot — including the re-binding. `commands.addKeyBinding` runs outside the
|
|
21
|
-
* reconcile pass, so it is unaffected and wins cleanly once the file-browser
|
|
22
|
-
* binding is gone.
|
|
3
|
+
* Bind Accel+Shift+F to the Search and Replace panel (VS Code parity). Core
|
|
4
|
+
* binds the chord to `filebrowser:toggle-main`; a `default_setting_overrides.d`
|
|
5
|
+
* override disables it. The re-binding is imperative: `reconcileShortcuts` keys
|
|
6
|
+
* on (keys, selector), so the disable would suppress a shipped default too.
|
|
23
7
|
*/
|
|
24
8
|
declare const plugin: JupyterFrontEndPlugin<void>;
|
|
25
9
|
export default plugin;
|
|
@@ -4,33 +4,15 @@ import { ITranslator, nullTranslator } from '@jupyterlab/translation';
|
|
|
4
4
|
const PLUGIN_ID = 'xtralab:search-replace';
|
|
5
5
|
const COMMAND_ID = 'xtralab:activate-search-replace';
|
|
6
6
|
/**
|
|
7
|
-
* Widget id of the
|
|
8
|
-
* extension
|
|
9
|
-
* so there is nothing to bind a shortcut to out of the box — this plugin adds
|
|
10
|
-
* the missing command.
|
|
7
|
+
* Widget id of the `jupyterlab-search-replace` left-sidebar panel; the
|
|
8
|
+
* extension registers no command of its own to bind a shortcut to.
|
|
11
9
|
*/
|
|
12
10
|
const SEARCH_REPLACE_WIDGET_ID = 'jp-search-replace';
|
|
13
11
|
/**
|
|
14
|
-
* Bind Accel+Shift+F
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* Two pieces are needed because that chord is already taken: JupyterLab core
|
|
19
|
-
* binds Accel+Shift+F to `filebrowser:toggle-main`.
|
|
20
|
-
*
|
|
21
|
-
* 1. The chord is freed declaratively. `SettingRegistry.reconcileShortcuts`
|
|
22
|
-
* keys collisions and disables on (keys, selector) — not on command — so the
|
|
23
|
-
* `@jupyterlab/shortcuts-extension:shortcuts` override in
|
|
24
|
-
* `default_setting_overrides.d/00-xtralab.json` disables the file-browser
|
|
25
|
-
* binding. The file browser stays reachable from its sidebar tab and the
|
|
26
|
-
* View menu; only the keyboard shortcut moves.
|
|
27
|
-
*
|
|
28
|
-
* 2. The new binding is added imperatively below rather than as another shipped
|
|
29
|
-
* default. A `disabled` default and a re-binding default land on the same
|
|
30
|
-
* (keys, selector) slot, and the disable suppresses every default on that
|
|
31
|
-
* slot — including the re-binding. `commands.addKeyBinding` runs outside the
|
|
32
|
-
* reconcile pass, so it is unaffected and wins cleanly once the file-browser
|
|
33
|
-
* binding is gone.
|
|
12
|
+
* Bind Accel+Shift+F to the Search and Replace panel (VS Code parity). Core
|
|
13
|
+
* binds the chord to `filebrowser:toggle-main`; a `default_setting_overrides.d`
|
|
14
|
+
* override disables it. The re-binding is imperative: `reconcileShortcuts` keys
|
|
15
|
+
* on (keys, selector), so the disable would suppress a shipped default too.
|
|
34
16
|
*/
|
|
35
17
|
const plugin = {
|
|
36
18
|
id: PLUGIN_ID,
|
|
@@ -45,9 +27,7 @@ const plugin = {
|
|
|
45
27
|
label: trans.__('Search and Replace'),
|
|
46
28
|
caption: trans.__('Show the Search and Replace panel'),
|
|
47
29
|
execute: () => {
|
|
48
|
-
//
|
|
49
|
-
// tab, and the widget focuses its search input from `onAfterShow`, so
|
|
50
|
-
// the user can start typing a query immediately. It no-ops if
|
|
30
|
+
// The widget focuses its search input from `onAfterShow`; no-ops if
|
|
51
31
|
// `jupyterlab-search-replace` is unavailable.
|
|
52
32
|
labShell.activateById(SEARCH_REPLACE_WIDGET_ID);
|
|
53
33
|
}
|
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
import { JupyterFrontEndPlugin } from '@jupyterlab/application';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* This is the kernel-free counterpart to running a notebook. A coding agent
|
|
7
|
-
* generates the content itself (a Vega-Lite spec, a Markdown explainer, an
|
|
8
|
-
* HTML fragment, an SVG, a base64 image) and hands it to this command, which
|
|
9
|
-
* renders it with the same renderers JupyterLab uses for cell output and docks
|
|
10
|
-
* the result beside the code. Nothing is written to disk and no kernel is
|
|
11
|
-
* required, so it works even where the kernel has no plotting libraries.
|
|
12
|
-
*
|
|
13
|
-
* Repeated calls with the same `id` reuse one panel, so a walkthrough can
|
|
14
|
-
* refresh the view in place instead of piling up tabs.
|
|
3
|
+
* Contributes `xtralab:show`: render a single MIME bundle into a panel with
|
|
4
|
+
* the same renderers JupyterLab uses for cell output — no kernel, no file on
|
|
5
|
+
* disk. Repeated calls with the same `id` reuse one panel.
|
|
15
6
|
*/
|
|
16
7
|
declare const plugin: JupyterFrontEndPlugin<void>;
|
|
17
8
|
export default plugin;
|
package/lib/showOutput/index.js
CHANGED
|
@@ -5,23 +5,11 @@ import { ITranslator, nullTranslator } from '@jupyterlab/translation';
|
|
|
5
5
|
import { Panel } from '@lumino/widgets';
|
|
6
6
|
import { coerceData } from '../mimeData';
|
|
7
7
|
const PLUGIN_ID = 'xtralab:show-output';
|
|
8
|
-
/**
|
|
9
|
-
* Render arbitrary rich content into a panel, with no notebook and no kernel.
|
|
10
|
-
*/
|
|
11
8
|
const SHOW_COMMAND = 'xtralab:show';
|
|
12
9
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* This is the kernel-free counterpart to running a notebook. A coding agent
|
|
17
|
-
* generates the content itself (a Vega-Lite spec, a Markdown explainer, an
|
|
18
|
-
* HTML fragment, an SVG, a base64 image) and hands it to this command, which
|
|
19
|
-
* renders it with the same renderers JupyterLab uses for cell output and docks
|
|
20
|
-
* the result beside the code. Nothing is written to disk and no kernel is
|
|
21
|
-
* required, so it works even where the kernel has no plotting libraries.
|
|
22
|
-
*
|
|
23
|
-
* Repeated calls with the same `id` reuse one panel, so a walkthrough can
|
|
24
|
-
* refresh the view in place instead of piling up tabs.
|
|
10
|
+
* Contributes `xtralab:show`: render a single MIME bundle into a panel with
|
|
11
|
+
* the same renderers JupyterLab uses for cell output — no kernel, no file on
|
|
12
|
+
* disk. Repeated calls with the same `id` reuse one panel.
|
|
25
13
|
*/
|
|
26
14
|
const plugin = {
|
|
27
15
|
id: PLUGIN_ID,
|
|
@@ -32,7 +20,6 @@ const plugin = {
|
|
|
32
20
|
activate: (app, rendermime, labShell, palette, translator) => {
|
|
33
21
|
const { commands } = app;
|
|
34
22
|
const trans = (translator !== null && translator !== void 0 ? translator : nullTranslator).load('jupyterlab');
|
|
35
|
-
// One reusable panel per `id`, so repeated shows refresh in place.
|
|
36
23
|
const panels = new Map();
|
|
37
24
|
commands.addCommand(SHOW_COMMAND, {
|
|
38
25
|
label: trans.__('Show Rich Output'),
|
|
@@ -89,16 +76,14 @@ const plugin = {
|
|
|
89
76
|
}
|
|
90
77
|
const model = rendermime.createModel({ data: bundle, trusted: true });
|
|
91
78
|
const renderer = rendermime.createRenderer(chosen);
|
|
92
|
-
//
|
|
93
|
-
//
|
|
94
|
-
// the content is taller than it (style/showOutput.css).
|
|
79
|
+
// Not a MainAreaWidget: it does not lay out its content in the side
|
|
80
|
+
// area; the panel scrolls via style/showOutput.css.
|
|
95
81
|
const widget = new Panel();
|
|
96
82
|
widget.addClass('jp-xtralab-ShowPanel');
|
|
97
83
|
widget.id = `xtralab-show-${id}`;
|
|
98
84
|
widget.title.label = label;
|
|
99
85
|
widget.title.closable = true;
|
|
100
86
|
widget.addWidget(renderer);
|
|
101
|
-
// Replace any existing panel with this id so shows refresh in place.
|
|
102
87
|
const existing = panels.get(id);
|
|
103
88
|
if (existing && !existing.isDisposed) {
|
|
104
89
|
existing.dispose();
|
|
@@ -110,8 +95,7 @@ const plugin = {
|
|
|
110
95
|
}
|
|
111
96
|
});
|
|
112
97
|
// Attach before rendering so renderers that need layout (Vega) size
|
|
113
|
-
// correctly.
|
|
114
|
-
// only split the document area when `area` is "main".
|
|
98
|
+
// correctly.
|
|
115
99
|
if (area === 'main') {
|
|
116
100
|
labShell.add(widget, 'main', {
|
|
117
101
|
mode,
|
package/lib/sidebar/index.d.ts
CHANGED
|
@@ -1,18 +1,9 @@
|
|
|
1
1
|
import { JupyterFrontEndPlugin } from '@jupyterlab/application';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* side
|
|
6
|
-
*
|
|
7
|
-
* the matching tab. The widget instance is preserved, so we can re-add it
|
|
8
|
-
* later via `labShell.add` with its original rank.
|
|
9
|
-
*
|
|
10
|
-
* The menu placement is contributed declaratively in
|
|
11
|
-
* `schema/sidebar.json`, so this plugin only registers commands and
|
|
12
|
-
* applies state — it does not touch `IMainMenu` directly.
|
|
13
|
-
*
|
|
14
|
-
* The preference is persisted to `xtralab:sidebar` settings so the choice
|
|
15
|
-
* survives reloads.
|
|
3
|
+
* Toggles individual sidebar tabs from View > Appearance > Sidebars. Hiding
|
|
4
|
+
* detaches the widget while keeping the instance for a later re-add; which
|
|
5
|
+
* side it came from is only tracked in-memory, so after a reload a re-shown
|
|
6
|
+
* tab lands on the left. Menu placement is declared in schema/sidebar.json.
|
|
16
7
|
*/
|
|
17
8
|
declare const plugin: JupyterFrontEndPlugin<void>;
|
|
18
9
|
export default plugin;
|
package/lib/sidebar/index.js
CHANGED
|
@@ -3,6 +3,27 @@ import { ISettingRegistry } from '@jupyterlab/settingregistry';
|
|
|
3
3
|
import { ITranslator, nullTranslator } from '@jupyterlab/translation';
|
|
4
4
|
const PLUGIN_ID = 'xtralab:sidebar';
|
|
5
5
|
const TARGETS = [
|
|
6
|
+
{
|
|
7
|
+
id: 'xtralab-running-terminals',
|
|
8
|
+
rank: 1,
|
|
9
|
+
settingKey: 'showTerminals',
|
|
10
|
+
command: 'xtralab:toggle-terminals',
|
|
11
|
+
label: trans => trans.__('Terminals')
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
id: 'xtralab:file-browser',
|
|
15
|
+
rank: 2,
|
|
16
|
+
settingKey: 'showFileBrowser',
|
|
17
|
+
command: 'xtralab:toggle-file-browser',
|
|
18
|
+
label: trans => trans.__('File Browser')
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: 'jp-git-sessions',
|
|
22
|
+
rank: 200,
|
|
23
|
+
settingKey: 'showGitPanel',
|
|
24
|
+
command: 'xtralab:toggle-git-panel',
|
|
25
|
+
label: trans => trans.__('Git')
|
|
26
|
+
},
|
|
6
27
|
{
|
|
7
28
|
id: 'filebrowser',
|
|
8
29
|
rank: 100,
|
|
@@ -16,55 +37,56 @@ const TARGETS = [
|
|
|
16
37
|
settingKey: 'showRunningSessions',
|
|
17
38
|
command: 'xtralab:toggle-running-sessions',
|
|
18
39
|
label: trans => trans.__('Running Terminals and Kernels')
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: 'jp-search-replace',
|
|
43
|
+
rank: 900,
|
|
44
|
+
settingKey: 'showSearchReplace',
|
|
45
|
+
command: 'xtralab:toggle-search-replace',
|
|
46
|
+
label: trans => trans.__('Search and Replace')
|
|
19
47
|
}
|
|
20
48
|
];
|
|
21
49
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* side
|
|
25
|
-
*
|
|
26
|
-
* the matching tab. The widget instance is preserved, so we can re-add it
|
|
27
|
-
* later via `labShell.add` with its original rank.
|
|
28
|
-
*
|
|
29
|
-
* The menu placement is contributed declaratively in
|
|
30
|
-
* `schema/sidebar.json`, so this plugin only registers commands and
|
|
31
|
-
* applies state — it does not touch `IMainMenu` directly.
|
|
32
|
-
*
|
|
33
|
-
* The preference is persisted to `xtralab:sidebar` settings so the choice
|
|
34
|
-
* survives reloads.
|
|
50
|
+
* Toggles individual sidebar tabs from View > Appearance > Sidebars. Hiding
|
|
51
|
+
* detaches the widget while keeping the instance for a later re-add; which
|
|
52
|
+
* side it came from is only tracked in-memory, so after a reload a re-shown
|
|
53
|
+
* tab lands on the left. Menu placement is declared in schema/sidebar.json.
|
|
35
54
|
*/
|
|
36
55
|
const plugin = {
|
|
37
56
|
id: PLUGIN_ID,
|
|
38
|
-
description: 'Toggle visibility of
|
|
57
|
+
description: 'Toggle visibility of individual sidebar tabs from the View menu.',
|
|
39
58
|
autoStart: true,
|
|
40
59
|
requires: [ILabShell],
|
|
41
60
|
optional: [ISettingRegistry, ITranslator],
|
|
42
61
|
activate: async (app, labShell, settingRegistry, translator) => {
|
|
43
62
|
const trans = (translator !== null && translator !== void 0 ? translator : nullTranslator).load('jupyterlab');
|
|
44
63
|
const { commands } = app;
|
|
45
|
-
//
|
|
46
|
-
//
|
|
47
|
-
// reachable through `labShell.widgets('left')` once removed, so a
|
|
48
|
-
// missing cache entry would leave us unable to bring the tab back.
|
|
64
|
+
// Detached widgets are unreachable via `labShell.widgets(...)`; keep
|
|
65
|
+
// instances here so hidden tabs can be re-added.
|
|
49
66
|
const widgetCache = new Map();
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
67
|
+
const hiddenFrom = new Map();
|
|
68
|
+
const findInSidebars = (id) => {
|
|
69
|
+
for (const area of ['left', 'right']) {
|
|
70
|
+
for (const widget of labShell.widgets(area)) {
|
|
71
|
+
if (widget.id === id) {
|
|
72
|
+
return { widget, area };
|
|
73
|
+
}
|
|
54
74
|
}
|
|
55
75
|
}
|
|
56
76
|
return null;
|
|
57
77
|
};
|
|
78
|
+
const locate = (id) => { var _a, _b; return (_b = (_a = findInSidebars(id)) === null || _a === void 0 ? void 0 : _a.area) !== null && _b !== void 0 ? _b : null; };
|
|
58
79
|
const captureWidget = (id) => {
|
|
80
|
+
var _a;
|
|
59
81
|
const cached = widgetCache.get(id);
|
|
60
82
|
if (cached && !cached.isDisposed) {
|
|
61
83
|
return cached;
|
|
62
84
|
}
|
|
63
|
-
const found =
|
|
85
|
+
const found = findInSidebars(id);
|
|
64
86
|
if (found) {
|
|
65
|
-
widgetCache.set(id, found);
|
|
87
|
+
widgetCache.set(id, found.widget);
|
|
66
88
|
}
|
|
67
|
-
return found;
|
|
89
|
+
return (_a = found === null || found === void 0 ? void 0 : found.widget) !== null && _a !== void 0 ? _a : null;
|
|
68
90
|
};
|
|
69
91
|
let settings = null;
|
|
70
92
|
const readPreference = (target) => {
|
|
@@ -75,22 +97,27 @@ const plugin = {
|
|
|
75
97
|
return typeof value === 'boolean' ? value : true;
|
|
76
98
|
};
|
|
77
99
|
const apply = (target) => {
|
|
100
|
+
var _a;
|
|
78
101
|
const widget = captureWidget(target.id);
|
|
79
102
|
if (!widget) {
|
|
80
|
-
// The upstream widget hasn't been added yet (or the extension is
|
|
81
|
-
// disabled). Nothing to do — the next time `apply` runs and finds
|
|
82
|
-
// it, the preference will take effect.
|
|
83
103
|
return;
|
|
84
104
|
}
|
|
85
|
-
const
|
|
105
|
+
const area = locate(target.id);
|
|
106
|
+
if (!area && widget.parent !== null) {
|
|
107
|
+
// Attached outside the sidebars — leave it alone.
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
86
110
|
const wantPresent = readPreference(target);
|
|
87
|
-
if (wantPresent && !
|
|
88
|
-
labShell.add(widget, 'left', {
|
|
111
|
+
if (wantPresent && !area) {
|
|
112
|
+
labShell.add(widget, (_a = hiddenFrom.get(target.id)) !== null && _a !== void 0 ? _a : 'left', {
|
|
113
|
+
rank: target.rank
|
|
114
|
+
});
|
|
115
|
+
hiddenFrom.delete(target.id);
|
|
89
116
|
}
|
|
90
|
-
else if (!wantPresent &&
|
|
91
|
-
|
|
92
|
-
//
|
|
93
|
-
// widget instance alive for a later re-add.
|
|
117
|
+
else if (!wantPresent && area) {
|
|
118
|
+
hiddenFrom.set(target.id, area);
|
|
119
|
+
// Detaching makes the SideBarHandler remove the tab while the
|
|
120
|
+
// widget instance stays alive for a later re-add.
|
|
94
121
|
widget.parent = null;
|
|
95
122
|
}
|
|
96
123
|
};
|
|
@@ -103,23 +130,26 @@ const plugin = {
|
|
|
103
130
|
commands.addCommand(target.command, {
|
|
104
131
|
label: target.label(trans),
|
|
105
132
|
isToggled: () => readPreference(target),
|
|
133
|
+
isVisible: () => {
|
|
134
|
+
// List only tabs this plugin can manage: in a sidebar, or
|
|
135
|
+
// hidden by this plugin (`parent === null`).
|
|
136
|
+
const widget = captureWidget(target.id);
|
|
137
|
+
return (widget !== null &&
|
|
138
|
+
(widget.parent === null || locate(target.id) !== null));
|
|
139
|
+
},
|
|
106
140
|
execute: async () => {
|
|
107
141
|
const next = !readPreference(target);
|
|
108
142
|
if (settings) {
|
|
109
143
|
try {
|
|
110
144
|
await settings.set(target.settingKey, next);
|
|
111
|
-
// `settings.changed`
|
|
112
|
-
// command-state refresh. Returning here keeps the toggle's
|
|
113
|
-
// single source of truth in the settings registry.
|
|
145
|
+
// `settings.changed` drives `apply` and the state refresh.
|
|
114
146
|
return;
|
|
115
147
|
}
|
|
116
148
|
catch (reason) {
|
|
117
149
|
console.error(`xtralab: failed to persist ${target.settingKey}`, reason);
|
|
118
150
|
}
|
|
119
151
|
}
|
|
120
|
-
// No settings
|
|
121
|
-
// back to applying the change in-memory so the toggle still
|
|
122
|
-
// works for the current session.
|
|
152
|
+
// No settings (or the write failed): apply in-memory for this session.
|
|
123
153
|
apply(target);
|
|
124
154
|
commands.notifyCommandChanged(target.command);
|
|
125
155
|
}
|
|
@@ -140,11 +170,8 @@ const plugin = {
|
|
|
140
170
|
}
|
|
141
171
|
}
|
|
142
172
|
void app.restored.then(() => {
|
|
143
|
-
// Capture
|
|
144
|
-
// recoverable
|
|
145
|
-
// the targets that need to stay visible — by capturing every target
|
|
146
|
-
// here we keep the cache populated for both directions of the
|
|
147
|
-
// toggle.
|
|
173
|
+
// Capture every widget before applying, so tabs hidden on startup
|
|
174
|
+
// stay recoverable.
|
|
148
175
|
for (const target of TARGETS) {
|
|
149
176
|
captureWidget(target.id);
|
|
150
177
|
}
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
import { JupyterFrontEndPlugin } from '@jupyterlab/application';
|
|
2
2
|
/**
|
|
3
|
-
* Turns the
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* A notification is suppressed while its terminal is the focused, active tab,
|
|
9
|
-
* and throttled per terminal. The desktop shell advertises
|
|
10
|
-
* `TERM_PROGRAM=iTerm.app` so agents emit OSC 9 in the first place, and the
|
|
11
|
-
* session name is forwarded so clicking a notification focuses the terminal
|
|
12
|
-
* that fired it.
|
|
3
|
+
* Turns the OSC 9 / OSC 777 / bell sequences agents emit into desktop
|
|
4
|
+
* notifications via `window.xtralab.notify` (desktop) or the web Notifications
|
|
5
|
+
* API — JupyterLab's xterm renders them but never forwards them to the OS.
|
|
6
|
+
* The desktop shell advertises `TERM_PROGRAM=iTerm.app` so agents emit OSC 9.
|
|
13
7
|
*/
|
|
14
8
|
declare const plugin: JupyterFrontEndPlugin<void>;
|
|
15
9
|
export default plugin;
|