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/menuBar/index.js
CHANGED
|
@@ -10,24 +10,14 @@ const PLUGIN_ID = 'xtralab:menu-bar';
|
|
|
10
10
|
const OPEN_COMMAND = 'xtralab:open-main-menu';
|
|
11
11
|
const TOGGLE_COMMAND = 'xtralab:toggle-menu-bar';
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* document `pointerdown` listener in the capture phase, which runs before
|
|
16
|
-
* the button's own mousedown handler — so without this window, pressing the
|
|
17
|
-
* button while the popup is open would close it and instantly reopen it.
|
|
13
|
+
* Guard after the popup closes: Lumino menus close on a capture-phase document
|
|
14
|
+
* pointerdown, before the button's mousedown, which would instantly reopen.
|
|
18
15
|
*/
|
|
19
16
|
const REOPEN_GUARD_MS = 250;
|
|
20
17
|
/**
|
|
21
|
-
* Collapse the main menu bar into a
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* menus as a vertical popup. The popup reuses the live `RankedMenu` instances
|
|
25
|
-
* owned by the `MainMenu`, so menus added or removed at runtime are reflected
|
|
26
|
-
* without duplication.
|
|
27
|
-
*
|
|
28
|
-
* Hiding covers the `jp-menu-panel` container too, which has its own
|
|
29
|
-
* `min-height` and would otherwise leave an empty strip. The "Show Menu Bar"
|
|
30
|
-
* toggle restores the classic bar.
|
|
18
|
+
* Collapse the main menu bar into a hamburger button whose popup reuses the
|
|
19
|
+
* live `RankedMenu` instances owned by `MainMenu`. Hiding covers the
|
|
20
|
+
* `jp-menu-panel` container too — its `min-height` would leave an empty strip.
|
|
31
21
|
*/
|
|
32
22
|
const plugin = {
|
|
33
23
|
id: PLUGIN_ID,
|
|
@@ -64,9 +54,8 @@ const plugin = {
|
|
|
64
54
|
const openMenu = () => {
|
|
65
55
|
var _a, _b;
|
|
66
56
|
if (visible) {
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
// compete with the bar for the same Menu instances.
|
|
57
|
+
// With the classic bar on screen, act like keyboard menu activation —
|
|
58
|
+
// a popup would compete with the bar for the same Menu instances.
|
|
70
59
|
mainMenu.activeIndex = 0;
|
|
71
60
|
mainMenu.openActiveMenu();
|
|
72
61
|
return;
|
|
@@ -74,13 +63,8 @@ const plugin = {
|
|
|
74
63
|
if (Date.now() - popupClosedAt < REOPEN_GUARD_MS) {
|
|
75
64
|
return;
|
|
76
65
|
}
|
|
77
|
-
//
|
|
78
|
-
//
|
|
79
|
-
// Menu rather than a MenuSvg: MenuSvg.insertItem re-wraps each
|
|
80
|
-
// submenu's renderer and insertItem on every call, which would pile
|
|
81
|
-
// wrappers onto the shared menus across reopens. The svg renderer and
|
|
82
|
-
// themed-container class are applied directly instead, matching how
|
|
83
|
-
// the real menus are constructed in MainMenu.
|
|
66
|
+
// A plain Menu rebuilt on every open; MenuSvg.insertItem would re-wrap
|
|
67
|
+
// each submenu's renderer per reopen, piling wrappers onto the shared menus.
|
|
84
68
|
if (popup === null) {
|
|
85
69
|
popup = new Menu({ commands, renderer: MenuSvg.defaultRenderer });
|
|
86
70
|
popup.addClass('jp-ThemedContainer');
|
|
@@ -153,9 +137,8 @@ const plugin = {
|
|
|
153
137
|
loaded.changed.connect(update);
|
|
154
138
|
})
|
|
155
139
|
.catch(reason => {
|
|
156
|
-
// Without settings the collapsed state cannot be managed
|
|
157
|
-
//
|
|
158
|
-
// the app with no reachable menus.
|
|
140
|
+
// Without settings the collapsed state cannot be managed and the button
|
|
141
|
+
// was never added; reveal the stock bar so menus stay reachable.
|
|
159
142
|
applyVisibility(true);
|
|
160
143
|
console.error(`Failed to load settings for ${PLUGIN_ID}`, reason);
|
|
161
144
|
});
|
package/lib/menus/index.d.ts
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import { JupyterFrontEndPlugin } from '@jupyterlab/application';
|
|
2
2
|
/**
|
|
3
|
-
* Hide the
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* cannot meaningfully invoke; remove them until a notebook or console is
|
|
7
|
-
* opened, then restore them at their original ranks.
|
|
8
|
-
*
|
|
9
|
-
* Detection is duck-typed on `sessionContext`: NotebookPanel and ConsolePanel
|
|
10
|
-
* both expose it, which avoids pulling in `@jupyterlab/notebook` and
|
|
11
|
-
* `@jupyterlab/console` just to identify their widgets.
|
|
3
|
+
* Hide the Run and Kernel menus while no kernel-using widget is open in the
|
|
4
|
+
* main area, then restore them at their original ranks — the agent-first
|
|
5
|
+
* launcher does not use kernels, so a fresh workspace should not surface them.
|
|
12
6
|
*/
|
|
13
7
|
declare const plugin: JupyterFrontEndPlugin<void>;
|
|
14
8
|
export default plugin;
|
package/lib/menus/index.js
CHANGED
|
@@ -2,15 +2,9 @@ import { ILabShell } from '@jupyterlab/application';
|
|
|
2
2
|
import { IMainMenu } from '@jupyterlab/mainmenu';
|
|
3
3
|
const PLUGIN_ID = 'xtralab:menus';
|
|
4
4
|
/**
|
|
5
|
-
* Hide the
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* cannot meaningfully invoke; remove them until a notebook or console is
|
|
9
|
-
* opened, then restore them at their original ranks.
|
|
10
|
-
*
|
|
11
|
-
* Detection is duck-typed on `sessionContext`: NotebookPanel and ConsolePanel
|
|
12
|
-
* both expose it, which avoids pulling in `@jupyterlab/notebook` and
|
|
13
|
-
* `@jupyterlab/console` just to identify their widgets.
|
|
5
|
+
* Hide the Run and Kernel menus while no kernel-using widget is open in the
|
|
6
|
+
* main area, then restore them at their original ranks — the agent-first
|
|
7
|
+
* launcher does not use kernels, so a fresh workspace should not surface them.
|
|
14
8
|
*/
|
|
15
9
|
const plugin = {
|
|
16
10
|
id: PLUGIN_ID,
|
|
@@ -19,27 +13,21 @@ const plugin = {
|
|
|
19
13
|
requires: [IMainMenu, ILabShell],
|
|
20
14
|
activate: (app, mainMenu, labShell) => {
|
|
21
15
|
var _a, _b;
|
|
22
|
-
// The interface types
|
|
23
|
-
//
|
|
24
|
-
// to MenuBar.removeMenu and IMainMenu.addMenu, which expect a `Menu`.
|
|
16
|
+
// The interface types extend IRankedMenu but the concrete instances are
|
|
17
|
+
// RankedMenu/Menu; cast for the MenuBar methods, which expect a `Menu`.
|
|
25
18
|
const menuBar = mainMenu;
|
|
26
19
|
const runMenu = mainMenu.runMenu;
|
|
27
20
|
const kernelMenu = mainMenu.kernelMenu;
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
// back to the hard-coded defaults from `MainMenu` keeps things sane
|
|
31
|
-
// if the schema ever omits the rank.
|
|
21
|
+
// Schema-assigned ranks so the menus reappear in their original slots;
|
|
22
|
+
// fall back to MainMenu's hard-coded defaults if the schema omits them.
|
|
32
23
|
const runRank = (_a = mainMenu.runMenu.rank) !== null && _a !== void 0 ? _a : 4;
|
|
33
24
|
const kernelRank = (_b = mainMenu.kernelMenu.rank) !== null && _b !== void 0 ? _b : 5;
|
|
34
25
|
const isPresent = (menu) => Array.from(menuBar.menus).indexOf(menu) > -1;
|
|
35
26
|
const update = () => {
|
|
36
27
|
const show = hasKernelWidget(labShell);
|
|
37
28
|
if (show) {
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
// so re-adding lands the menu at the wrong position. Insert
|
|
41
|
-
// directly on the MenuBar by walking current menus and finding
|
|
42
|
-
// the first sibling with a higher rank.
|
|
29
|
+
// Not `mainMenu.addMenu`: its insertion index comes from a private
|
|
30
|
+
// `_items` array that `removeMenu` doesn't update, misplacing re-adds.
|
|
43
31
|
if (!isPresent(runMenu)) {
|
|
44
32
|
insertByRank(menuBar, runMenu, runRank);
|
|
45
33
|
}
|
|
@@ -63,11 +51,9 @@ const plugin = {
|
|
|
63
51
|
}
|
|
64
52
|
};
|
|
65
53
|
/**
|
|
66
|
-
* True iff any
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* `@jupyterlab/notebook` and `@jupyterlab/console` into xtralab's bundle
|
|
70
|
-
* just to do an `instanceof` check.
|
|
54
|
+
* True iff any main-area widget exposes a `sessionContext` (NotebookPanel,
|
|
55
|
+
* ConsolePanel, kernel-attached editors) — duck-typed to keep
|
|
56
|
+
* `@jupyterlab/notebook` and `@jupyterlab/console` out of the bundle.
|
|
71
57
|
*/
|
|
72
58
|
function hasKernelWidget(labShell) {
|
|
73
59
|
for (const widget of labShell.widgets('main')) {
|
|
@@ -82,10 +68,8 @@ function hasSessionContext(widget) {
|
|
|
82
68
|
return (candidate.sessionContext !== null && candidate.sessionContext !== undefined);
|
|
83
69
|
}
|
|
84
70
|
/**
|
|
85
|
-
* Insert `menu`
|
|
86
|
-
*
|
|
87
|
-
* rank are treated as +Infinity so they sink to the end (matching the
|
|
88
|
-
* convention in `MenuFactory.createMenus`).
|
|
71
|
+
* Insert `menu` at the slot dictated by `rank`; rank-less menus count as
|
|
72
|
+
* +Infinity and sink to the end, matching `MenuFactory.createMenus`.
|
|
89
73
|
*/
|
|
90
74
|
function insertByRank(menuBar, menu, rank) {
|
|
91
75
|
const menus = menuBar.menus;
|
package/lib/omnibox/files.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The workspace file list, cached briefly so reopening the omnibox
|
|
3
|
-
*
|
|
4
|
-
* extension is absent) resolves to an empty list so file search degrades to
|
|
5
|
-
* "no results" instead of surfacing an error.
|
|
2
|
+
* The workspace file list, cached briefly so reopening the omnibox reuses one
|
|
3
|
+
* scan. A failed fetch resolves to an empty list.
|
|
6
4
|
*/
|
|
7
5
|
export declare function loadWorkspaceFiles(): Promise<string[]>;
|
package/lib/omnibox/files.js
CHANGED
|
@@ -2,13 +2,9 @@ import { URLExt } from '@jupyterlab/coreutils';
|
|
|
2
2
|
import { ServerConnection } from '@jupyterlab/services';
|
|
3
3
|
/**
|
|
4
4
|
* Fetch and flatten the workspace file list from `jupyterlab-quickopen`'s
|
|
5
|
-
* server endpoint
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* listing honors the same server-side `.gitignore` filtering quickopen does
|
|
9
|
-
* (xtralab ships `respectGitignore: true`) in a single request. The endpoint
|
|
10
|
-
* only exists when quickopen's server extension is installed and the server
|
|
11
|
-
* reads a local filesystem; callers treat a rejection as "no file results".
|
|
5
|
+
* server endpoint, which applies server-side `.gitignore` filtering in one
|
|
6
|
+
* request. Rejects when the server extension is absent; callers treat that as
|
|
7
|
+
* "no file results".
|
|
12
8
|
*/
|
|
13
9
|
async function fetchWorkspaceFiles(respectGitignore = true) {
|
|
14
10
|
const settings = ServerConnection.makeSettings();
|
|
@@ -36,10 +32,8 @@ async function fetchWorkspaceFiles(respectGitignore = true) {
|
|
|
36
32
|
const CACHE_TTL_MS = 15000;
|
|
37
33
|
let cache = null;
|
|
38
34
|
/**
|
|
39
|
-
* The workspace file list, cached briefly so reopening the omnibox
|
|
40
|
-
*
|
|
41
|
-
* extension is absent) resolves to an empty list so file search degrades to
|
|
42
|
-
* "no results" instead of surfacing an error.
|
|
35
|
+
* The workspace file list, cached briefly so reopening the omnibox reuses one
|
|
36
|
+
* scan. A failed fetch resolves to an empty list.
|
|
43
37
|
*/
|
|
44
38
|
export function loadWorkspaceFiles() {
|
|
45
39
|
const now = Date.now();
|
package/lib/omnibox/index.d.ts
CHANGED
|
@@ -1,20 +1,10 @@
|
|
|
1
1
|
import { JupyterFrontEndPlugin } from '@jupyterlab/application';
|
|
2
2
|
import { IOmnibox } from './tokens';
|
|
3
3
|
/**
|
|
4
|
-
* The omnibox: a
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* (running it in a fresh terminal through the launcher's
|
|
9
|
-
* `xtralab:start-agent:<id>` commands). It is opened by the top-bar command
|
|
10
|
-
* bar.
|
|
11
|
-
*
|
|
12
|
-
* Commands run and files opened through the overlay are remembered (persisted
|
|
13
|
-
* in the state database) and offered again at the top while the query is
|
|
14
|
-
* empty; the `maxNumberRecents` setting caps how many of each are kept.
|
|
15
|
-
*
|
|
16
|
-
* The agent rows come from the launcher's `IAgentRegistry`; when the launcher
|
|
17
|
-
* is disabled the omnibox still searches files and commands.
|
|
4
|
+
* The omnibox: a launcher overlay that fuzzy-searches workspace files and
|
|
5
|
+
* commands and routes a typed prompt to a configured agent in a fresh
|
|
6
|
+
* terminal. Recently used commands and files persist in the state database;
|
|
7
|
+
* without the launcher it still searches files and commands.
|
|
18
8
|
*/
|
|
19
9
|
declare const plugin: JupyterFrontEndPlugin<IOmnibox>;
|
|
20
10
|
export default plugin;
|
package/lib/omnibox/index.js
CHANGED
|
@@ -9,20 +9,10 @@ import { IOmnibox, OMNIBOX_OPEN_COMMAND } from './tokens';
|
|
|
9
9
|
import { OmniboxWidget } from './widget';
|
|
10
10
|
const PLUGIN_ID = 'xtralab:omnibox';
|
|
11
11
|
/**
|
|
12
|
-
* The omnibox: a
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* (running it in a fresh terminal through the launcher's
|
|
17
|
-
* `xtralab:start-agent:<id>` commands). It is opened by the top-bar command
|
|
18
|
-
* bar.
|
|
19
|
-
*
|
|
20
|
-
* Commands run and files opened through the overlay are remembered (persisted
|
|
21
|
-
* in the state database) and offered again at the top while the query is
|
|
22
|
-
* empty; the `maxNumberRecents` setting caps how many of each are kept.
|
|
23
|
-
*
|
|
24
|
-
* The agent rows come from the launcher's `IAgentRegistry`; when the launcher
|
|
25
|
-
* is disabled the omnibox still searches files and commands.
|
|
12
|
+
* The omnibox: a launcher overlay that fuzzy-searches workspace files and
|
|
13
|
+
* commands and routes a typed prompt to a configured agent in a fresh
|
|
14
|
+
* terminal. Recently used commands and files persist in the state database;
|
|
15
|
+
* without the launcher it still searches files and commands.
|
|
26
16
|
*/
|
|
27
17
|
const plugin = {
|
|
28
18
|
id: PLUGIN_ID,
|
|
@@ -40,21 +30,15 @@ const plugin = {
|
|
|
40
30
|
const { commands, docRegistry } = app;
|
|
41
31
|
const trans = (translator !== null && translator !== void 0 ? translator : nullTranslator).load('jupyterlab');
|
|
42
32
|
const placeholder = trans.__('Search files and commands, or ask an agent…');
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
// exposes no item list and the widget itself is unreachable through the
|
|
46
|
-
// shell (`LabShell.add` defers it until layout restore, after which the
|
|
47
|
-
// modal setting re-parents it out of the left area). The wrapper's
|
|
48
|
-
// `_palette` field is private in TypeScript only, so read it guarded.
|
|
33
|
+
// `ICommandPalette` exposes no item list and the palette widget is
|
|
34
|
+
// unreachable through the shell; duck-read the wrapper's TS-only-private `_palette`.
|
|
49
35
|
const paletteItems = () => {
|
|
50
36
|
const widget = palette === null || palette === void 0 ? void 0 : palette._palette;
|
|
51
37
|
return widget instanceof CommandPalette ? [...widget.items] : [];
|
|
52
38
|
};
|
|
53
39
|
const recents = new OmniboxRecents({ state });
|
|
54
|
-
// Restore
|
|
55
|
-
// `
|
|
56
|
-
// would permanently drop entries beyond it whenever the user configured a
|
|
57
|
-
// larger cap and the state fetch won the race against the settings load.
|
|
40
|
+
// Restore only after the configured cap is known: `restore` trims to
|
|
41
|
+
// `maxItems`, so restoring at the default could permanently drop entries.
|
|
58
42
|
if (settingRegistry) {
|
|
59
43
|
void settingRegistry
|
|
60
44
|
.load(PLUGIN_ID)
|
|
@@ -85,7 +69,7 @@ const plugin = {
|
|
|
85
69
|
};
|
|
86
70
|
const open = (query) => {
|
|
87
71
|
// Reopen fresh each time so the input resets and the agent snapshot is
|
|
88
|
-
// current; the file list
|
|
72
|
+
// current; the file list stays cached (files.ts).
|
|
89
73
|
close();
|
|
90
74
|
const widget = new OmniboxWidget({
|
|
91
75
|
commands,
|
|
@@ -110,7 +94,6 @@ const plugin = {
|
|
|
110
94
|
label: trans.__('Search…'),
|
|
111
95
|
caption: trans.__('Search files and commands, or ask an agent'),
|
|
112
96
|
execute: args => {
|
|
113
|
-
// Toggle: a second press (e.g. of the keyboard shortcut) closes it.
|
|
114
97
|
if (current && !current.isDisposed) {
|
|
115
98
|
close();
|
|
116
99
|
return;
|
|
@@ -119,7 +102,6 @@ const plugin = {
|
|
|
119
102
|
open(typeof query === 'string' ? query : undefined);
|
|
120
103
|
}
|
|
121
104
|
});
|
|
122
|
-
// Open the omnibox with Cmd/Ctrl+K, the common "command center" chord.
|
|
123
105
|
commands.addKeyBinding({
|
|
124
106
|
command: OMNIBOX_OPEN_COMMAND,
|
|
125
107
|
keys: ['Accel K'],
|
package/lib/omnibox/model.d.ts
CHANGED
|
@@ -5,14 +5,14 @@ import type { CommandRegistry } from '@lumino/commands';
|
|
|
5
5
|
import type { CommandPalette } from '@lumino/widgets';
|
|
6
6
|
import type { IAgent } from '../launcher/agents';
|
|
7
7
|
import type { OmniboxRecents } from './recents';
|
|
8
|
-
/**
|
|
9
|
-
* The source a result row came from, used to group rows under a header.
|
|
10
|
-
*/
|
|
11
8
|
type OmniboxItemKind = 'command' | 'file' | 'agent';
|
|
12
9
|
/**
|
|
13
10
|
* A single result row, with the action it runs when chosen.
|
|
14
11
|
*/
|
|
15
12
|
export interface IOmniboxItem {
|
|
13
|
+
/**
|
|
14
|
+
* The source category of the row: command, file, or agent.
|
|
15
|
+
*/
|
|
16
16
|
kind: OmniboxItemKind;
|
|
17
17
|
/**
|
|
18
18
|
* Stable React key.
|
|
@@ -47,34 +47,62 @@ interface IOmniboxSections {
|
|
|
47
47
|
* Recently used commands and files, shown while the term is empty.
|
|
48
48
|
*/
|
|
49
49
|
recent: IOmniboxItem[];
|
|
50
|
+
/**
|
|
51
|
+
* Commands matching the term.
|
|
52
|
+
*/
|
|
50
53
|
commands: IOmniboxItem[];
|
|
54
|
+
/**
|
|
55
|
+
* Workspace files matching the term.
|
|
56
|
+
*/
|
|
51
57
|
files: IOmniboxItem[];
|
|
58
|
+
/**
|
|
59
|
+
* Per-agent "Ask" rows carrying the term as a prompt.
|
|
60
|
+
*/
|
|
52
61
|
agents: IOmniboxItem[];
|
|
53
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Inputs for {@link computeSections}.
|
|
65
|
+
*/
|
|
54
66
|
interface IComputeOptions {
|
|
67
|
+
/**
|
|
68
|
+
* Raw query text from the input.
|
|
69
|
+
*/
|
|
55
70
|
query: string;
|
|
71
|
+
/**
|
|
72
|
+
* The command registry used to look up and execute commands.
|
|
73
|
+
*/
|
|
56
74
|
commands: CommandRegistry;
|
|
57
75
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
76
|
+
* Palette items, whose labels are computed with each item's args — the only
|
|
77
|
+
* form in which entries like "Use Theme: …" exist.
|
|
60
78
|
*/
|
|
61
79
|
paletteItems: ReadonlyArray<CommandPalette.IItem>;
|
|
80
|
+
/**
|
|
81
|
+
* The document registry used to pick file icons.
|
|
82
|
+
*/
|
|
62
83
|
docRegistry: DocumentRegistry;
|
|
84
|
+
/**
|
|
85
|
+
* The available agents; prompt-capable ones get "Ask" rows.
|
|
86
|
+
*/
|
|
63
87
|
agents: IAgent[];
|
|
88
|
+
/**
|
|
89
|
+
* Workspace-relative file paths to match against.
|
|
90
|
+
*/
|
|
64
91
|
files: string[];
|
|
65
92
|
/**
|
|
66
93
|
* Recently-used tracker; `null` disables the recent rows and recording.
|
|
67
94
|
*/
|
|
68
95
|
recents: OmniboxRecents | null;
|
|
96
|
+
/**
|
|
97
|
+
* Translation bundle for row labels.
|
|
98
|
+
*/
|
|
69
99
|
trans: TranslationBundle;
|
|
70
100
|
}
|
|
71
101
|
/**
|
|
72
102
|
* Build the grouped result set for a query. A leading `>` searches only
|
|
73
|
-
* commands
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* rows for the active mode instead (and the widget shows a hint when there
|
|
77
|
-
* are none).
|
|
103
|
+
* commands, `/` only files; otherwise every prompt-capable agent also gets an
|
|
104
|
+
* "Ask" row carrying the query as its prompt. An empty term yields the
|
|
105
|
+
* recently used rows for the active mode.
|
|
78
106
|
*/
|
|
79
107
|
export declare function computeSections(options: IComputeOptions): IOmniboxSections;
|
|
80
108
|
export {};
|
package/lib/omnibox/model.js
CHANGED
|
@@ -3,20 +3,14 @@ import { StringExt } from '@lumino/algorithm';
|
|
|
3
3
|
import { agentCommandId } from '../launcher/tokens';
|
|
4
4
|
const COMMAND_LIMIT = 7;
|
|
5
5
|
const FILE_LIMIT = 10;
|
|
6
|
-
/**
|
|
7
|
-
* Prefixes that narrow the search to a single source: a leading `>` to
|
|
8
|
-
* commands, a leading `/` to files (relative paths never start with `/`, so it
|
|
9
|
-
* is unambiguous). Without a prefix, every source is searched.
|
|
10
|
-
*/
|
|
11
6
|
const COMMAND_PREFIX = '>';
|
|
7
|
+
// Unambiguous: workspace-relative paths never start with '/'.
|
|
12
8
|
const FILE_PREFIX = '/';
|
|
13
9
|
/**
|
|
14
10
|
* Build the grouped result set for a query. A leading `>` searches only
|
|
15
|
-
* commands
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* rows for the active mode instead (and the widget shows a hint when there
|
|
19
|
-
* are none).
|
|
11
|
+
* commands, `/` only files; otherwise every prompt-capable agent also gets an
|
|
12
|
+
* "Ask" row carrying the query as its prompt. An empty term yields the
|
|
13
|
+
* recently used rows for the active mode.
|
|
20
14
|
*/
|
|
21
15
|
export function computeSections(options) {
|
|
22
16
|
const { query, commands, agents, trans } = options;
|
|
@@ -43,13 +37,11 @@ export function computeSections(options) {
|
|
|
43
37
|
recent: [],
|
|
44
38
|
commands: mode === 'files' ? [] : matchCommands(options, term),
|
|
45
39
|
files: mode === 'commands' ? [] : matchFiles(options, term),
|
|
46
|
-
// Agents only in the unprefixed view; the prompt is the full typed query.
|
|
47
40
|
agents: mode === 'all' ? buildAgentItems(commands, agents, term, trans) : []
|
|
48
41
|
};
|
|
49
42
|
}
|
|
50
43
|
/**
|
|
51
|
-
* Run a command and record the use on success, so
|
|
52
|
-
* the recents list.
|
|
44
|
+
* Run a command and record the use on success, so failures never enter the recents.
|
|
53
45
|
*/
|
|
54
46
|
function executeCommand(commands, recents, id, args) {
|
|
55
47
|
void commands
|
|
@@ -61,9 +53,6 @@ function executeCommand(commands, recents, id, args) {
|
|
|
61
53
|
console.error(`xtralab omnibox: command "${id}" failed`, reason);
|
|
62
54
|
});
|
|
63
55
|
}
|
|
64
|
-
/**
|
|
65
|
-
* Open a file and record the use on success.
|
|
66
|
-
*/
|
|
67
56
|
function openFile(commands, recents, path) {
|
|
68
57
|
void commands
|
|
69
58
|
.execute('docmanager:open', { path })
|
|
@@ -76,9 +65,8 @@ function openFile(commands, recents, path) {
|
|
|
76
65
|
}
|
|
77
66
|
/**
|
|
78
67
|
* Read a command's label, visibility and caption, or `null` when the command
|
|
79
|
-
* is missing, hidden, label-less, or its accessors throw (a
|
|
80
|
-
*
|
|
81
|
-
* doesn't provide).
|
|
68
|
+
* is missing, hidden, label-less, or its accessors throw (they can assume a
|
|
69
|
+
* context the omnibox doesn't provide).
|
|
82
70
|
*/
|
|
83
71
|
function commandDisplay(commands, id, args) {
|
|
84
72
|
if (!commands.hasCommand(id)) {
|
|
@@ -97,10 +85,9 @@ function commandDisplay(commands, id, args) {
|
|
|
97
85
|
}
|
|
98
86
|
/**
|
|
99
87
|
* The recently used rows for the empty term: both kinds interleaved by
|
|
100
|
-
* recency
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
* unavailable — file entries are shown as recorded).
|
|
88
|
+
* recency, or only the mode's kind under a bare `>` or `/`. Unresolvable
|
|
89
|
+
* commands are dropped, as are files absent from the workspace listing once
|
|
90
|
+
* it loads.
|
|
104
91
|
*/
|
|
105
92
|
function buildRecentItems(options, mode) {
|
|
106
93
|
var _a;
|
|
@@ -147,11 +134,10 @@ function buildRecentItems(options, mode) {
|
|
|
147
134
|
return items;
|
|
148
135
|
}
|
|
149
136
|
/**
|
|
150
|
-
* Match
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
* pass so a command never also surfaces under its argless label.
|
|
137
|
+
* Match palette items first — their labels carry per-item args (one "Use
|
|
138
|
+
* Theme: …" per theme), which a registry scan can never produce — then
|
|
139
|
+
* registry commands the palette doesn't present, skipping palette-covered ids
|
|
140
|
+
* so a command never also surfaces under its argless label.
|
|
155
141
|
*/
|
|
156
142
|
function matchCommands(options, term) {
|
|
157
143
|
const { commands, paletteItems, recents } = options;
|
|
@@ -166,8 +152,6 @@ function matchCommands(options, term) {
|
|
|
166
152
|
let visible = true;
|
|
167
153
|
let caption = '';
|
|
168
154
|
try {
|
|
169
|
-
// An item's accessors can throw if the command assumes a context (e.g.
|
|
170
|
-
// an active notebook) the omnibox doesn't provide; skip those.
|
|
171
155
|
label = item.label;
|
|
172
156
|
visible = item.isVisible;
|
|
173
157
|
caption = item.caption;
|
|
@@ -209,8 +193,6 @@ function matchCommands(options, term) {
|
|
|
209
193
|
let visible = true;
|
|
210
194
|
let caption = '';
|
|
211
195
|
try {
|
|
212
|
-
// A command's accessors can throw if they assume a context (e.g. an
|
|
213
|
-
// active notebook) the omnibox doesn't provide; skip those.
|
|
214
196
|
label = commands.label(id);
|
|
215
197
|
visible = commands.isVisible(id);
|
|
216
198
|
caption = commands.caption(id);
|
|
@@ -276,7 +258,7 @@ function buildAgentItems(commands, agents, prompt, trans) {
|
|
|
276
258
|
const items = [];
|
|
277
259
|
for (const agent of agents) {
|
|
278
260
|
// Agents without `promptArgs` can't take an inline prompt (the launcher
|
|
279
|
-
// would drop it)
|
|
261
|
+
// would drop it).
|
|
280
262
|
if (agent.promptArgs === undefined) {
|
|
281
263
|
continue;
|
|
282
264
|
}
|
package/lib/omnibox/recents.d.ts
CHANGED
|
@@ -1,52 +1,50 @@
|
|
|
1
1
|
import type { IStateDB } from '@jupyterlab/statedb';
|
|
2
2
|
import type { ReadonlyPartialJSONObject } from '@lumino/coreutils';
|
|
3
|
-
/**
|
|
4
|
-
* Kinds of omnibox results whose uses are recorded.
|
|
5
|
-
*/
|
|
6
3
|
export type RecentKind = 'command' | 'file';
|
|
7
4
|
/**
|
|
8
5
|
* A single recorded use: a command that was run or a file that was opened.
|
|
9
6
|
*/
|
|
10
7
|
interface IRecentEntry {
|
|
8
|
+
/**
|
|
9
|
+
* Whether the entry records a command run or a file opened.
|
|
10
|
+
*/
|
|
11
11
|
kind: RecentKind;
|
|
12
12
|
/**
|
|
13
13
|
* The command id, or the workspace-relative file path.
|
|
14
14
|
*/
|
|
15
15
|
id: string;
|
|
16
16
|
/**
|
|
17
|
-
* Arguments the command ran with, for palette-style entries whose label
|
|
18
|
-
*
|
|
17
|
+
* Arguments the command ran with, for palette-style entries whose label and
|
|
18
|
+
* behavior depend on them.
|
|
19
19
|
*/
|
|
20
20
|
args?: ReadonlyPartialJSONObject;
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
|
-
* A most-recently-used list of omnibox results,
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* state database so they survive reloads. Without a state database the list
|
|
27
|
-
* still works for the lifetime of the page.
|
|
23
|
+
* A most-recently-used list of omnibox results, most-recent-first, capped at
|
|
24
|
+
* `maxItems` per kind and persisted through the state database. Without a
|
|
25
|
+
* state database it still works for the lifetime of the page.
|
|
28
26
|
*/
|
|
29
27
|
export declare class OmniboxRecents {
|
|
30
28
|
constructor(options?: OmniboxRecents.IOptions);
|
|
31
29
|
/**
|
|
32
|
-
* Maximum
|
|
33
|
-
* immediately; `0` disables recents entirely.
|
|
30
|
+
* Maximum entries kept per kind; lowering trims immediately, `0` disables recents.
|
|
34
31
|
*/
|
|
35
32
|
get maxItems(): number;
|
|
33
|
+
/**
|
|
34
|
+
* Set the maximum entries kept per kind.
|
|
35
|
+
*/
|
|
36
36
|
set maxItems(value: number);
|
|
37
37
|
/**
|
|
38
|
-
* The recorded entries, most recent first
|
|
39
|
-
* one kind.
|
|
38
|
+
* The recorded entries, most recent first, optionally filtered to one kind.
|
|
40
39
|
*/
|
|
41
40
|
entries(kind?: RecentKind): IRecentEntry[];
|
|
42
41
|
/**
|
|
43
|
-
* Record a use
|
|
44
|
-
* the front of its kind's list.
|
|
42
|
+
* Record a use, moving the entry to the front of its kind's list.
|
|
45
43
|
*/
|
|
46
44
|
touch(kind: RecentKind, id: string, args?: ReadonlyPartialJSONObject): void;
|
|
47
45
|
/**
|
|
48
46
|
* Load the persisted list. Entries recorded before the load completes stay
|
|
49
|
-
*
|
|
47
|
+
* ahead of the restored history.
|
|
50
48
|
*/
|
|
51
49
|
restore(): Promise<void>;
|
|
52
50
|
/**
|