xtralab 0.11.1 → 0.12.0
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 +37 -231
- package/lib/agentSessions.d.ts +6 -2
- package/lib/askAgent/editorSelection.d.ts +53 -0
- package/lib/askAgent/editorSelection.js +95 -0
- package/lib/askAgent/icons.d.ts +7 -0
- package/lib/askAgent/icons.js +15 -0
- package/lib/askAgent/index.d.ts +32 -0
- package/lib/askAgent/index.js +741 -0
- package/lib/askAgent/popup.d.ts +83 -0
- package/lib/askAgent/popup.js +221 -0
- package/lib/askAgent/prompt.d.ts +24 -0
- package/lib/askAgent/prompt.js +116 -0
- package/lib/askAgent/queue.d.ts +93 -0
- package/lib/askAgent/queue.js +207 -0
- package/lib/askAgent/queuePanel.d.ts +76 -0
- package/lib/askAgent/queuePanel.js +188 -0
- package/lib/askAgent/targetPicker.d.ts +58 -0
- package/lib/askAgent/targetPicker.js +74 -0
- package/lib/askAgent/tokens.d.ts +124 -0
- package/lib/askAgent/tokens.js +13 -0
- package/lib/commandBar/index.d.ts +12 -8
- package/lib/commandBar/index.js +58 -41
- package/lib/editorBreadcrumbs/index.js +9 -4
- package/lib/editorBreadcrumbs/widget.d.ts +7 -7
- package/lib/editorBreadcrumbs/widget.js +6 -8
- package/lib/fileBrowser/commands.d.ts +2 -8
- package/lib/fileBrowser/commands.js +39 -30
- package/lib/fileBrowser/contents.d.ts +8 -3
- package/lib/fileBrowser/fileBrowser.d.ts +2 -1
- package/lib/fileBrowser/widget.d.ts +5 -9
- package/lib/fileBrowser/widget.js +1 -1
- package/lib/fileTypeIcons/index.js +5 -2
- package/lib/git/api.d.ts +0 -26
- package/lib/git/api.js +2 -44
- package/lib/git/askRequest.d.ts +23 -0
- package/lib/git/askRequest.js +90 -0
- package/lib/git/commands.d.ts +14 -2
- package/lib/git/commands.js +16 -13
- package/lib/git/diffModel.d.ts +1 -9
- package/lib/git/diffModel.js +1 -1
- package/lib/git/diffProvider.js +8 -3
- package/lib/git/diffSurface.d.ts +19 -2
- package/lib/git/diffSurface.js +64 -18
- package/lib/git/diffTheme.d.ts +0 -4
- package/lib/git/diffTheme.js +1 -1
- package/lib/git/diffWidget.d.ts +9 -0
- package/lib/git/diffWidget.js +38 -10
- package/lib/git/imageDiff.d.ts +17 -4
- package/lib/git/imageDiff.js +90 -30
- package/lib/git/index.js +7 -2
- package/lib/git/notebookDiff.d.ts +10 -67
- package/lib/git/notebookDiff.js +62 -69
- package/lib/git/tokens.d.ts +5 -2
- package/lib/highlight/index.js +12 -8
- package/lib/index.js +2 -0
- package/lib/launcher/agents.js +3 -4
- package/lib/launcher/commands.d.ts +6 -2
- package/lib/launcher/dashboard.d.ts +8 -1
- package/lib/launcher/dashboard.js +39 -33
- package/lib/launcher/editorRegistry.js +5 -3
- package/lib/launcher/editors.d.ts +15 -5
- package/lib/launcher/icons.d.ts +0 -37
- package/lib/launcher/icons.js +11 -12
- package/lib/launcher/index.js +2 -1
- package/lib/launcher/invocation.d.ts +0 -15
- package/lib/launcher/invocation.js +1 -1
- package/lib/launcher/schemaDefaults.d.ts +3 -1
- package/lib/launcher/schemaDefaults.js +3 -1
- package/lib/mimeData.d.ts +7 -0
- package/lib/mimeData.js +16 -0
- package/lib/omnibox/index.d.ts +4 -0
- package/lib/omnibox/index.js +43 -2
- package/lib/omnibox/model.d.ts +43 -14
- package/lib/omnibox/model.js +117 -14
- package/lib/omnibox/recents.d.ts +65 -0
- package/lib/omnibox/recents.js +109 -0
- package/lib/omnibox/tokens.d.ts +6 -2
- package/lib/omnibox/widget.d.ts +23 -6
- package/lib/omnibox/widget.js +26 -7
- package/lib/showOutput/index.js +15 -18
- package/lib/terminals/agentTerminals.d.ts +63 -0
- package/lib/terminals/agentTerminals.js +157 -0
- package/lib/terminals/index.d.ts +7 -1
- package/lib/terminals/index.js +50 -30
- package/lib/terminals/model.d.ts +11 -2
- package/lib/terminals/model.js +27 -8
- package/lib/terminals/tokens.d.ts +66 -0
- package/lib/terminals/tokens.js +7 -0
- package/lib/terminals/widget.d.ts +3 -6
- package/lib/terminals/widget.js +1 -1
- package/lib/topBar/index.js +3 -3
- package/lib/walkthrough/index.js +14 -3
- package/lib/walkthrough/panel.d.ts +12 -4
- package/lib/walkthrough/panel.js +9 -3
- package/package.json +49 -51
- package/schema/command-bar.json +10 -0
- package/schema/omnibox.json +15 -0
- package/src/agentSessions.ts +6 -2
- package/src/askAgent/editorSelection.ts +138 -0
- package/src/askAgent/icons.ts +16 -0
- package/src/askAgent/index.ts +915 -0
- package/src/askAgent/popup.tsx +407 -0
- package/src/askAgent/prompt.ts +144 -0
- package/src/askAgent/queue.ts +269 -0
- package/src/askAgent/queuePanel.tsx +418 -0
- package/src/askAgent/targetPicker.tsx +209 -0
- package/src/askAgent/tokens.ts +139 -0
- package/src/commandBar/index.ts +75 -49
- package/src/editorBreadcrumbs/index.ts +14 -4
- package/src/editorBreadcrumbs/widget.ts +11 -9
- package/src/fileBrowser/commands.ts +45 -31
- package/src/fileBrowser/contents.ts +7 -3
- package/src/fileBrowser/fileBrowser.tsx +1 -1
- package/src/fileBrowser/widget.tsx +5 -3
- package/src/fileTypeIcons/index.ts +6 -3
- package/src/git/api.ts +2 -61
- package/src/git/askRequest.ts +113 -0
- package/src/git/commands.ts +41 -14
- package/src/git/diffModel.ts +1 -1
- package/src/git/diffProvider.tsx +11 -3
- package/src/git/diffSurface.tsx +114 -22
- package/src/git/diffTheme.ts +1 -1
- package/src/git/diffWidget.tsx +54 -7
- package/src/git/imageDiff.tsx +169 -58
- package/src/git/index.ts +10 -2
- package/src/git/notebookDiff.tsx +91 -57
- package/src/git/tokens.ts +4 -2
- package/src/highlight/index.ts +12 -8
- package/src/index.ts +2 -0
- package/src/launcher/agents.ts +3 -4
- package/src/launcher/commands.ts +6 -2
- package/src/launcher/dashboard.tsx +86 -38
- package/src/launcher/editorRegistry.ts +10 -4
- package/src/launcher/editors.ts +15 -5
- package/src/launcher/icons.ts +11 -12
- package/src/launcher/index.ts +2 -1
- package/src/launcher/invocation.ts +1 -1
- package/src/launcher/schemaDefaults.ts +3 -1
- package/src/mimeData.ts +20 -0
- package/src/omnibox/index.ts +48 -1
- package/src/omnibox/model.ts +173 -33
- package/src/omnibox/recents.ts +155 -0
- package/src/omnibox/tokens.ts +6 -2
- package/src/omnibox/widget.tsx +54 -13
- package/src/showOutput/index.ts +20 -23
- package/src/terminals/agentTerminals.ts +238 -0
- package/src/terminals/index.ts +54 -30
- package/src/terminals/model.ts +28 -7
- package/src/terminals/tokens.ts +77 -0
- package/src/terminals/widget.tsx +4 -2
- package/src/topBar/index.ts +12 -6
- package/src/walkthrough/index.ts +19 -4
- package/src/walkthrough/panel.ts +15 -5
- package/style/askAgent.css +544 -0
- package/style/commandBar.css +12 -33
- package/style/git.css +72 -31
- package/style/index.css +1 -0
- package/style/index.js +2 -0
- package/style/topBar.css +4 -4
|
@@ -4,12 +4,16 @@ import type { CommandRegistry } from '@lumino/commands';
|
|
|
4
4
|
import type { ReadonlyPartialJSONValue } from '@lumino/coreutils';
|
|
5
5
|
import type { Message } from '@lumino/messaging';
|
|
6
6
|
import { Panel } from '@lumino/widgets';
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* A rich visual embedded in a step (rendered through the rendermime registry).
|
|
9
|
+
*/
|
|
8
10
|
export interface IWalkthroughMedia {
|
|
9
11
|
mimeType: string;
|
|
10
12
|
data: ReadonlyPartialJSONValue;
|
|
11
13
|
}
|
|
12
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* One step of a walkthrough. Every field is optional, but a step needs at least one.
|
|
16
|
+
*/
|
|
13
17
|
export interface IWalkthroughStep {
|
|
14
18
|
title?: string;
|
|
15
19
|
body?: string;
|
|
@@ -36,7 +40,9 @@ export declare namespace WalkthroughPanel {
|
|
|
36
40
|
*/
|
|
37
41
|
export declare class WalkthroughPanel extends Panel {
|
|
38
42
|
constructor(options: WalkthroughPanel.IOptions);
|
|
39
|
-
/**
|
|
43
|
+
/**
|
|
44
|
+
* Remove every step, leaving an empty panel.
|
|
45
|
+
*/
|
|
40
46
|
clear(): void;
|
|
41
47
|
/**
|
|
42
48
|
* Dispose on close (e.g. the close button when the panel has been dragged to
|
|
@@ -44,7 +50,9 @@ export declare class WalkthroughPanel extends Panel {
|
|
|
44
50
|
* next `xtralab:walkthrough` call recreates the panel in the side area.
|
|
45
51
|
*/
|
|
46
52
|
protected onCloseRequest(msg: Message): void;
|
|
47
|
-
/**
|
|
53
|
+
/**
|
|
54
|
+
* Append a step and scroll it into view.
|
|
55
|
+
*/
|
|
48
56
|
addStep(step: IWalkthroughStep): Promise<void>;
|
|
49
57
|
private _render;
|
|
50
58
|
private _jumpButton;
|
package/lib/walkthrough/panel.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { fileIcon } from '@jupyterlab/ui-components';
|
|
2
2
|
import { Panel, Widget } from '@lumino/widgets';
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Command the jump links dispatch; keeps the panel decoupled from the plugin.
|
|
5
|
+
*/
|
|
4
6
|
const HIGHLIGHT_LINES_COMMAND = 'xtralab:highlight-lines';
|
|
5
7
|
/**
|
|
6
8
|
* A read-only, scrollable column of walkthrough steps for the side area.
|
|
@@ -19,7 +21,9 @@ export class WalkthroughPanel extends Panel {
|
|
|
19
21
|
this._trans = options.trans;
|
|
20
22
|
this.addClass('jp-xtralab-Walkthrough');
|
|
21
23
|
}
|
|
22
|
-
/**
|
|
24
|
+
/**
|
|
25
|
+
* Remove every step, leaving an empty panel.
|
|
26
|
+
*/
|
|
23
27
|
clear() {
|
|
24
28
|
while (this.widgets.length > 0) {
|
|
25
29
|
this.widgets[0].dispose();
|
|
@@ -34,7 +38,9 @@ export class WalkthroughPanel extends Panel {
|
|
|
34
38
|
super.onCloseRequest(msg);
|
|
35
39
|
this.dispose();
|
|
36
40
|
}
|
|
37
|
-
/**
|
|
41
|
+
/**
|
|
42
|
+
* Append a step and scroll it into view.
|
|
43
|
+
*/
|
|
38
44
|
async addStep(step) {
|
|
39
45
|
const card = new Panel();
|
|
40
46
|
card.addClass('jp-xtralab-Walkthrough-step');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xtralab",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "An opinionated JupyterLab meta-package that bundles a curated set of extensions, ships a path-first file browser, renders jupyterlab-git's text, notebook and image diffs with its own viewers, and applies a quieter default workspace configuration.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jupyter",
|
|
@@ -58,65 +58,61 @@
|
|
|
58
58
|
"watch:labextension": "jupyter-builder watch ."
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@codemirror/language": "^6.12.
|
|
62
|
-
"@codemirror/state": "^6.
|
|
63
|
-
"@codemirror/view": "^6.
|
|
64
|
-
"@jupyterlab/application": "^4.6.0
|
|
65
|
-
"@jupyterlab/apputils": "^4.7.0
|
|
66
|
-
"@jupyterlab/codemirror": "^4.6.0
|
|
67
|
-
"@jupyterlab/coreutils": "^6.6.0
|
|
68
|
-
"@jupyterlab/docmanager": "^4.6.0
|
|
69
|
-
"@jupyterlab/docregistry": "^4.6.0
|
|
70
|
-
"@jupyterlab/
|
|
71
|
-
"@jupyterlab/
|
|
72
|
-
"@jupyterlab/mainmenu": "^4.6.0
|
|
73
|
-
"@jupyterlab/nbformat": "^4.6.0
|
|
74
|
-
"@jupyterlab/
|
|
75
|
-
"@jupyterlab/
|
|
76
|
-
"@jupyterlab/
|
|
77
|
-
"@jupyterlab/
|
|
78
|
-
"@jupyterlab/
|
|
79
|
-
"@jupyterlab/
|
|
80
|
-
"@jupyterlab/
|
|
81
|
-
"@
|
|
82
|
-
"@
|
|
83
|
-
"@lumino/
|
|
84
|
-
"@lumino/
|
|
85
|
-
"@lumino/
|
|
86
|
-
"@lumino/
|
|
61
|
+
"@codemirror/language": "^6.12.3",
|
|
62
|
+
"@codemirror/state": "^6.7.0",
|
|
63
|
+
"@codemirror/view": "^6.43.2",
|
|
64
|
+
"@jupyterlab/application": "^4.6.0",
|
|
65
|
+
"@jupyterlab/apputils": "^4.7.0",
|
|
66
|
+
"@jupyterlab/codemirror": "^4.6.0",
|
|
67
|
+
"@jupyterlab/coreutils": "^6.6.0",
|
|
68
|
+
"@jupyterlab/docmanager": "^4.6.0",
|
|
69
|
+
"@jupyterlab/docregistry": "^4.6.0",
|
|
70
|
+
"@jupyterlab/fileeditor": "^4.6.0",
|
|
71
|
+
"@jupyterlab/git": "^0.54.0",
|
|
72
|
+
"@jupyterlab/mainmenu": "^4.6.0",
|
|
73
|
+
"@jupyterlab/nbformat": "^4.6.0",
|
|
74
|
+
"@jupyterlab/notebook": "^4.6.0",
|
|
75
|
+
"@jupyterlab/outputarea": "^4.6.0",
|
|
76
|
+
"@jupyterlab/rendermime": "^4.6.0",
|
|
77
|
+
"@jupyterlab/services": "^7.6.0",
|
|
78
|
+
"@jupyterlab/settingregistry": "^4.6.0",
|
|
79
|
+
"@jupyterlab/statedb": "^4.6.0",
|
|
80
|
+
"@jupyterlab/terminal": "^4.6.0",
|
|
81
|
+
"@jupyterlab/translation": "^4.6.0",
|
|
82
|
+
"@jupyterlab/ui-components": "^4.6.0",
|
|
83
|
+
"@lumino/algorithm": "^2.0.4",
|
|
84
|
+
"@lumino/commands": "^2.3.3",
|
|
85
|
+
"@lumino/coreutils": "^2.2.2",
|
|
86
|
+
"@lumino/disposable": "^2.1.5",
|
|
87
|
+
"@lumino/dragdrop": "^2.1.8",
|
|
88
|
+
"@lumino/messaging": "^2.0.4",
|
|
87
89
|
"@lumino/polling": "^2.1.5",
|
|
88
|
-
"@lumino/signaling": "^2.
|
|
89
|
-
"@lumino/widgets": "^2.
|
|
90
|
-
"@pierre/diffs": "^1.2.
|
|
90
|
+
"@lumino/signaling": "^2.1.5",
|
|
91
|
+
"@lumino/widgets": "^2.8.0",
|
|
92
|
+
"@pierre/diffs": "^1.2.11",
|
|
91
93
|
"@pierre/trees": "1.0.0-beta.4",
|
|
92
94
|
"detect-indent": "^7.0.2",
|
|
93
95
|
"ignore": "^5.3.2",
|
|
94
|
-
"react": "^18.
|
|
95
|
-
"react-dom": "^18.2.0"
|
|
96
|
+
"react": "^18.3.1"
|
|
96
97
|
},
|
|
97
98
|
"devDependencies": {
|
|
98
|
-
"@jupyter/builder": "^1.0.
|
|
99
|
-
"@types/
|
|
100
|
-
"@
|
|
101
|
-
"@
|
|
102
|
-
"
|
|
103
|
-
"
|
|
104
|
-
"
|
|
105
|
-
"
|
|
106
|
-
"
|
|
107
|
-
"
|
|
108
|
-
"
|
|
109
|
-
"prettier": "^3.0.0",
|
|
110
|
-
"rimraf": "^5.0.1",
|
|
111
|
-
"source-map-loader": "^1.0.2",
|
|
112
|
-
"style-loader": "^3.3.1",
|
|
113
|
-
"stylelint": "^15.10.1",
|
|
99
|
+
"@jupyter/builder": "^1.0.2",
|
|
100
|
+
"@types/react": "^18.3.31",
|
|
101
|
+
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
|
102
|
+
"@typescript-eslint/parser": "^6.21.0",
|
|
103
|
+
"eslint": "^8.57.1",
|
|
104
|
+
"eslint-config-prettier": "^8.10.2",
|
|
105
|
+
"eslint-plugin-prettier": "^5.5.6",
|
|
106
|
+
"npm-run-all2": "^7.0.2",
|
|
107
|
+
"prettier": "^3.8.4",
|
|
108
|
+
"rimraf": "^5.0.10",
|
|
109
|
+
"stylelint": "^15.11.0",
|
|
114
110
|
"stylelint-config-recommended": "^13.0.0",
|
|
115
111
|
"stylelint-config-standard": "^34.0.0",
|
|
116
|
-
"stylelint-csstree-validator": "^3.
|
|
117
|
-
"stylelint-prettier": "^4.
|
|
112
|
+
"stylelint-csstree-validator": "^3.1.0",
|
|
113
|
+
"stylelint-prettier": "^4.1.0",
|
|
118
114
|
"typescript": "~5.5.4",
|
|
119
|
-
"yjs": "^13.
|
|
115
|
+
"yjs": "^13.6.31"
|
|
120
116
|
},
|
|
121
117
|
"pnpm": {
|
|
122
118
|
"ignoredBuiltDependencies": [
|
|
@@ -153,6 +149,8 @@
|
|
|
153
149
|
"dist",
|
|
154
150
|
"coverage",
|
|
155
151
|
"**/*.d.ts",
|
|
152
|
+
"docs",
|
|
153
|
+
"ui-tests",
|
|
156
154
|
"desktop/out",
|
|
157
155
|
"desktop/dist",
|
|
158
156
|
"desktop/python/wheels",
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "xtralab Command Bar",
|
|
3
|
+
"description": "The search-bar-styled pill in the top bar that opens the omnibox.",
|
|
4
|
+
"jupyter.lab.toolbars": {
|
|
5
|
+
"TopBar": [{ "name": "omnibox", "rank": 100 }]
|
|
6
|
+
},
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {},
|
|
9
|
+
"additionalProperties": false
|
|
10
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "xtralab Omnibox",
|
|
3
|
+
"description": "The launcher overlay that searches files and commands and prompts agents.",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"properties": {
|
|
6
|
+
"maxNumberRecents": {
|
|
7
|
+
"type": "integer",
|
|
8
|
+
"title": "Recent items number",
|
|
9
|
+
"description": "Number of recently used commands and files (each) the omnibox remembers and shows at the top before you type a query. Set to 0 to disable recent items.",
|
|
10
|
+
"default": 5,
|
|
11
|
+
"minimum": 0
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"additionalProperties": false
|
|
15
|
+
}
|
package/src/agentSessions.ts
CHANGED
|
@@ -28,10 +28,14 @@ export interface IAgentSessions {
|
|
|
28
28
|
*/
|
|
29
29
|
get(sessionName: string): string | null;
|
|
30
30
|
|
|
31
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* Record that a session was launched as the given agent command.
|
|
33
|
+
*/
|
|
32
34
|
set(sessionName: string, command: string): void;
|
|
33
35
|
|
|
34
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Forget a session — called when it shuts down so the map stays bounded.
|
|
38
|
+
*/
|
|
35
39
|
delete(sessionName: string): void;
|
|
36
40
|
|
|
37
41
|
/**
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type { JupyterFrontEnd } from '@jupyterlab/application';
|
|
2
|
+
import { CodeMirrorEditor } from '@jupyterlab/codemirror';
|
|
3
|
+
import { FileEditor } from '@jupyterlab/fileeditor';
|
|
4
|
+
import { NotebookPanel } from '@jupyterlab/notebook';
|
|
5
|
+
import type { EditorView } from '@codemirror/view';
|
|
6
|
+
import type { Widget } from '@lumino/widgets';
|
|
7
|
+
|
|
8
|
+
import type { IAskAgentContext, IAskAgentRequest } from './tokens';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A CodeMirror view a selection can be asked about, plus the context needed
|
|
12
|
+
* to describe it to an agent: the document path and, for notebooks, which
|
|
13
|
+
* cell the view belongs to.
|
|
14
|
+
*/
|
|
15
|
+
interface IEditorTarget {
|
|
16
|
+
view: EditorView;
|
|
17
|
+
path: string;
|
|
18
|
+
cell?: {
|
|
19
|
+
index: number;
|
|
20
|
+
type: string;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Resolve the CodeMirror view a selection in `widget` would live in, or
|
|
26
|
+
* `null` when the widget holds no such editor. Two widget shapes are
|
|
27
|
+
* recognized:
|
|
28
|
+
*
|
|
29
|
+
* - a notebook panel, where the active cell carries the editor and
|
|
30
|
+
* `activeCellIndex` names its 0-based position in the nbformat `cells`
|
|
31
|
+
* array. A rendered markdown cell keeps its (hidden) editor, but a
|
|
32
|
+
* selection in the rendered HTML never passes {@link domSelectionInView},
|
|
33
|
+
* so no pill appears there; and
|
|
34
|
+
* - a document widget whose content is a `FileEditor`. The wrapper is not
|
|
35
|
+
* checked with `instanceof DocumentWidget`: `@jupyterlab/docregistry` is
|
|
36
|
+
* not a core singleton, so another copy of the class could be in play.
|
|
37
|
+
* `FileEditor` and `NotebookPanel` come from singleton packages.
|
|
38
|
+
*/
|
|
39
|
+
export function resolveEditorTarget(
|
|
40
|
+
widget: Widget | null
|
|
41
|
+
): IEditorTarget | null {
|
|
42
|
+
if (widget instanceof NotebookPanel) {
|
|
43
|
+
const cell = widget.content.activeCell;
|
|
44
|
+
if (cell !== null && cell.editor instanceof CodeMirrorEditor) {
|
|
45
|
+
return {
|
|
46
|
+
view: cell.editor.editor,
|
|
47
|
+
path: widget.context.path,
|
|
48
|
+
cell: { index: widget.content.activeCellIndex, type: cell.model.type }
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const content = (widget as { content?: unknown } | null)?.content;
|
|
55
|
+
if (
|
|
56
|
+
content instanceof FileEditor &&
|
|
57
|
+
content.editor instanceof CodeMirrorEditor
|
|
58
|
+
) {
|
|
59
|
+
return { view: content.editor.editor, path: content.context.path };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Whether the current DOM selection lives inside `view`. Guards the
|
|
67
|
+
* selection-change listener against selections made elsewhere (a terminal,
|
|
68
|
+
* a sidebar, another notebook cell) while the widget owning `view` happens
|
|
69
|
+
* to be the shell's current widget.
|
|
70
|
+
*/
|
|
71
|
+
export function domSelectionInView(
|
|
72
|
+
view: EditorView,
|
|
73
|
+
selection: Selection
|
|
74
|
+
): boolean {
|
|
75
|
+
const node = selection.anchorNode;
|
|
76
|
+
const element =
|
|
77
|
+
node instanceof Element ? node : (node?.parentElement ?? null);
|
|
78
|
+
return element !== null && view.dom.contains(element);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Build an ask-agent request from the current selection in the shell's
|
|
83
|
+
* current widget — a file editor or the active notebook cell — or return
|
|
84
|
+
* `null` when that widget holds no CodeMirror document editor.
|
|
85
|
+
*
|
|
86
|
+
* With `allowEmpty`, a collapsed selection falls back to the cursor's line
|
|
87
|
+
* (used by the command/shortcut path so it works without a mouse
|
|
88
|
+
* selection); otherwise an empty selection yields `null`.
|
|
89
|
+
*/
|
|
90
|
+
export function editorAskRequest(
|
|
91
|
+
app: JupyterFrontEnd,
|
|
92
|
+
options: { allowEmpty?: boolean } = {}
|
|
93
|
+
): IAskAgentRequest | null {
|
|
94
|
+
const target = resolveEditorTarget(app.shell.currentWidget);
|
|
95
|
+
if (target === null) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const { view, path, cell } = target;
|
|
100
|
+
const { state } = view;
|
|
101
|
+
const main = state.selection.main;
|
|
102
|
+
if (main.empty && options.allowEmpty !== true) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const startLine = state.doc.lineAt(main.from).number;
|
|
107
|
+
let endLine: number;
|
|
108
|
+
let text: string;
|
|
109
|
+
if (main.empty) {
|
|
110
|
+
endLine = startLine;
|
|
111
|
+
text = state.doc.lineAt(main.from).text;
|
|
112
|
+
} else {
|
|
113
|
+
// A selection that ends exactly at the start of a line (the common
|
|
114
|
+
// "drag over whole lines" gesture) should not count that line.
|
|
115
|
+
const endPos =
|
|
116
|
+
main.to === state.doc.lineAt(main.to).from ? main.to - 1 : main.to;
|
|
117
|
+
endLine = state.doc.lineAt(endPos).number;
|
|
118
|
+
text = state.sliceDoc(main.from, main.to);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Anchor the popup at the selection head (where the cursor ended up).
|
|
122
|
+
// `coordsAtPos` returns `null` for positions scrolled out of view.
|
|
123
|
+
const coords = view.coordsAtPos(main.head);
|
|
124
|
+
const anchor = coords
|
|
125
|
+
? new DOMRect(
|
|
126
|
+
coords.left,
|
|
127
|
+
coords.top,
|
|
128
|
+
Math.max(1, coords.right - coords.left),
|
|
129
|
+
Math.max(1, coords.bottom - coords.top)
|
|
130
|
+
)
|
|
131
|
+
: null;
|
|
132
|
+
|
|
133
|
+
const context: IAskAgentContext = { path, startLine, endLine, text };
|
|
134
|
+
if (cell !== undefined) {
|
|
135
|
+
context.cell = cell;
|
|
136
|
+
}
|
|
137
|
+
return { context, anchor };
|
|
138
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { LabIcon } from '@jupyterlab/ui-components';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Four-point sparkle used by the ask-agent affordances (selection pill,
|
|
5
|
+
* command palette entry). Drawn in-repo; the `jp-icon3` class lets the
|
|
6
|
+
* active theme recolor the glyph like other JupyterLab UI icons.
|
|
7
|
+
*/
|
|
8
|
+
export const askAgentIcon = new LabIcon({
|
|
9
|
+
name: 'xtralab:ask-agent',
|
|
10
|
+
svgstr: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
|
11
|
+
<g class="jp-icon3" fill="#616161">
|
|
12
|
+
<path d="M6 1l1 4 4 1-4 1-1 4-1-4-4-1 4-1 1-4z"/>
|
|
13
|
+
<path d="M12 9l.7 2.3L15 12l-2.3.7L12 15l-.7-2.3L9 12l2.3-.7L12 9z"/>
|
|
14
|
+
</g>
|
|
15
|
+
</svg>`
|
|
16
|
+
});
|