xtralab 0.15.0 → 0.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -30
- package/lib/about/icons.d.ts +0 -5
- package/lib/about/icons.js +0 -5
- package/lib/about/index.d.ts +4 -8
- package/lib/about/index.js +6 -17
- package/lib/agentSessions.d.ts +9 -29
- package/lib/agentSessions.js +2 -7
- package/lib/askAgent/editorSelection.d.ts +20 -26
- package/lib/askAgent/editorSelection.js +11 -26
- package/lib/askAgent/icons.d.ts +2 -3
- package/lib/askAgent/icons.js +2 -3
- package/lib/askAgent/index.d.ts +4 -26
- package/lib/askAgent/index.js +54 -158
- package/lib/askAgent/popup.d.ts +12 -16
- package/lib/askAgent/popup.js +18 -37
- package/lib/askAgent/prompt.d.ts +3 -5
- package/lib/askAgent/prompt.js +6 -19
- package/lib/askAgent/queue.d.ts +11 -21
- package/lib/askAgent/queue.js +9 -19
- package/lib/askAgent/queuePanel.d.ts +13 -18
- package/lib/askAgent/queuePanel.js +15 -37
- package/lib/askAgent/targetPicker.d.ts +2 -9
- package/lib/askAgent/targetPicker.js +6 -11
- package/lib/askAgent/tokens.d.ts +32 -46
- package/lib/askAgent/tokens.js +4 -6
- package/lib/commandBar/index.d.ts +4 -13
- package/lib/commandBar/index.js +21 -39
- package/lib/customPanel/index.js +15 -0
- package/lib/editorBreadcrumbs/index.d.ts +3 -6
- package/lib/editorBreadcrumbs/index.js +10 -6
- package/lib/editorBreadcrumbs/widget.d.ts +17 -4
- package/lib/editorBreadcrumbs/widget.js +11 -17
- package/lib/editorIndent/index.d.ts +4 -12
- package/lib/editorIndent/index.js +8 -23
- package/lib/fileBrowser/commands.d.ts +29 -19
- package/lib/fileBrowser/commands.js +83 -97
- package/lib/fileBrowser/contents.d.ts +3 -0
- package/lib/fileBrowser/dragAndDrop.d.ts +17 -4
- package/lib/fileBrowser/dragAndDrop.js +2 -7
- package/lib/fileBrowser/fileBrowser.d.ts +19 -9
- package/lib/fileBrowser/fileBrowser.js +70 -222
- package/lib/fileBrowser/gitStatus.d.ts +16 -10
- package/lib/fileBrowser/gitStatus.js +31 -30
- package/lib/fileBrowser/gitignore.d.ts +4 -17
- package/lib/fileBrowser/gitignore.js +4 -25
- package/lib/fileBrowser/icons.d.ts +7 -17
- package/lib/fileBrowser/icons.js +25 -80
- package/lib/fileBrowser/index.js +2 -4
- package/lib/fileBrowser/widget.d.ts +141 -48
- package/lib/fileBrowser/widget.js +102 -4
- package/lib/fileTypeIcons/index.js +0 -10
- package/lib/git/api.d.ts +5 -13
- package/lib/git/api.js +10 -36
- package/lib/git/askRequest.d.ts +4 -8
- package/lib/git/askRequest.js +6 -20
- package/lib/git/commands.d.ts +45 -5
- package/lib/git/commands.js +20 -13
- package/lib/git/diffModel.js +4 -0
- package/lib/git/diffPreferences.d.ts +90 -0
- package/lib/git/diffPreferences.js +107 -0
- package/lib/git/diffProvider.js +10 -2
- package/lib/git/diffSurface.d.ts +64 -63
- package/lib/git/diffSurface.js +72 -213
- package/lib/git/diffTheme.d.ts +7 -0
- package/lib/git/diffTheme.js +23 -0
- package/lib/git/diffWidget.d.ts +70 -14
- package/lib/git/diffWidget.js +100 -94
- package/lib/git/imageDiff.d.ts +14 -6
- package/lib/git/imageDiff.js +19 -75
- package/lib/git/index.d.ts +0 -3
- package/lib/git/index.js +44 -10
- package/lib/git/notebookDiff.d.ts +110 -33
- package/lib/git/notebookDiff.js +55 -197
- package/lib/git/tokens.d.ts +73 -31
- package/lib/git/tokens.js +2 -3
- package/lib/highlight/index.d.ts +4 -10
- package/lib/highlight/index.js +10 -41
- package/lib/index.d.ts +0 -9
- package/lib/index.js +0 -9
- package/lib/launcher/agents.d.ts +55 -51
- package/lib/launcher/agents.js +15 -57
- package/lib/launcher/availability.d.ts +3 -9
- package/lib/launcher/availability.js +3 -9
- package/lib/launcher/commands.d.ts +7 -32
- package/lib/launcher/commands.js +14 -45
- package/lib/launcher/dashboard.d.ts +19 -24
- package/lib/launcher/dashboard.js +21 -67
- package/lib/launcher/editorRegistry.d.ts +10 -22
- package/lib/launcher/editorRegistry.js +14 -18
- package/lib/launcher/editors.d.ts +39 -45
- package/lib/launcher/editors.js +8 -34
- package/lib/launcher/icons.d.ts +0 -12
- package/lib/launcher/icons.js +5 -39
- package/lib/launcher/index.js +12 -55
- package/lib/launcher/invocation.d.ts +4 -10
- package/lib/launcher/invocation.js +7 -22
- package/lib/launcher/registry.d.ts +9 -7
- package/lib/launcher/registry.js +9 -7
- package/lib/launcher/tokens.d.ts +10 -22
- package/lib/launcher/tokens.js +5 -8
- package/lib/menuBar/index.d.ts +3 -10
- package/lib/menuBar/index.js +11 -28
- package/lib/menus/index.d.ts +3 -9
- package/lib/menus/index.js +14 -30
- package/lib/omnibox/files.d.ts +2 -4
- package/lib/omnibox/files.js +5 -11
- package/lib/omnibox/index.d.ts +4 -14
- package/lib/omnibox/index.js +9 -27
- package/lib/omnibox/model.d.ts +38 -10
- package/lib/omnibox/model.js +15 -33
- package/lib/omnibox/recents.d.ts +15 -17
- package/lib/omnibox/recents.js +12 -17
- package/lib/omnibox/tokens.d.ts +5 -10
- package/lib/omnibox/tokens.js +2 -6
- package/lib/omnibox/widget.d.ts +11 -7
- package/lib/omnibox/widget.js +8 -16
- package/lib/searchReplace/index.d.ts +4 -20
- package/lib/searchReplace/index.js +7 -27
- package/lib/showOutput/index.d.ts +3 -12
- package/lib/showOutput/index.js +6 -22
- package/lib/sidebar/index.d.ts +4 -7
- package/lib/sidebar/index.js +5 -12
- package/lib/terminalNotifications/index.d.ts +4 -10
- package/lib/terminalNotifications/index.js +6 -20
- package/lib/terminals/agentTerminals.d.ts +12 -5
- package/lib/terminals/agentTerminals.js +25 -44
- package/lib/terminals/detection.d.ts +4 -8
- package/lib/terminals/detection.js +4 -8
- package/lib/terminals/index.d.ts +0 -35
- package/lib/terminals/index.js +12 -101
- package/lib/terminals/model.d.ts +64 -139
- package/lib/terminals/model.js +80 -220
- package/lib/terminals/tokens.d.ts +11 -22
- package/lib/terminals/tokens.js +2 -2
- package/lib/terminals/widget.d.ts +43 -13
- package/lib/terminals/widget.js +33 -18
- package/lib/topBar/icons.d.ts +3 -8
- package/lib/topBar/icons.js +3 -8
- package/lib/topBar/index.d.ts +4 -11
- package/lib/topBar/index.js +10 -38
- package/lib/walkthrough/index.d.ts +4 -9
- package/lib/walkthrough/index.js +6 -20
- package/lib/walkthrough/panel.d.ts +40 -9
- package/lib/walkthrough/panel.js +4 -10
- package/package.json +5 -3
- package/schema/git-diff-preferences.json +42 -0
- package/src/about/icons.ts +0 -5
- package/src/about/index.tsx +6 -17
- package/src/agentSessions.ts +9 -29
- package/src/askAgent/editorSelection.ts +22 -29
- package/src/askAgent/icons.ts +2 -3
- package/src/askAgent/index.ts +54 -158
- package/src/askAgent/popup.tsx +23 -45
- package/src/askAgent/prompt.ts +6 -19
- package/src/askAgent/queue.ts +13 -24
- package/src/askAgent/queuePanel.tsx +21 -46
- package/src/askAgent/targetPicker.tsx +5 -15
- package/src/askAgent/tokens.ts +32 -46
- package/src/commandBar/index.ts +24 -39
- package/src/customPanel/index.ts +15 -0
- package/src/editorBreadcrumbs/index.ts +10 -6
- package/src/editorBreadcrumbs/widget.ts +23 -17
- package/src/editorIndent/index.ts +17 -23
- package/src/fileBrowser/commands.ts +119 -96
- package/src/fileBrowser/contents.ts +3 -0
- package/src/fileBrowser/dragAndDrop.ts +17 -7
- package/src/fileBrowser/fileBrowser.tsx +86 -230
- package/src/fileBrowser/gitStatus.ts +36 -33
- package/src/fileBrowser/gitignore.ts +4 -25
- package/src/fileBrowser/icons.ts +25 -80
- package/src/fileBrowser/index.ts +2 -4
- package/src/fileBrowser/widget.tsx +171 -50
- package/src/fileTypeIcons/index.ts +0 -10
- package/src/git/api.ts +10 -36
- package/src/git/askRequest.ts +6 -20
- package/src/git/commands.ts +83 -11
- package/src/git/diffModel.ts +25 -0
- package/src/git/diffPreferences.ts +192 -0
- package/src/git/diffProvider.tsx +11 -2
- package/src/git/diffSurface.tsx +165 -286
- package/src/git/diffTheme.ts +24 -0
- package/src/git/diffWidget.tsx +194 -134
- package/src/git/imageDiff.tsx +56 -84
- package/src/git/index.ts +54 -10
- package/src/git/notebookDiff.tsx +214 -240
- package/src/git/tokens.ts +73 -31
- package/src/highlight/index.ts +10 -41
- package/src/index.ts +0 -9
- package/src/launcher/agents.ts +64 -95
- package/src/launcher/availability.ts +3 -9
- package/src/launcher/commands.ts +14 -51
- package/src/launcher/dashboard.tsx +49 -88
- package/src/launcher/editorRegistry.ts +21 -29
- package/src/launcher/editors.ts +39 -58
- package/src/launcher/icons.ts +5 -39
- package/src/launcher/index.ts +12 -55
- package/src/launcher/invocation.ts +7 -22
- package/src/launcher/registry.ts +9 -7
- package/src/launcher/tokens.ts +10 -22
- package/src/menuBar/index.ts +11 -28
- package/src/menus/index.ts +14 -30
- package/src/omnibox/files.ts +10 -14
- package/src/omnibox/index.ts +9 -27
- package/src/omnibox/model.ts +50 -38
- package/src/omnibox/recents.ts +17 -22
- package/src/omnibox/tokens.ts +5 -10
- package/src/omnibox/widget.tsx +14 -19
- package/src/searchReplace/index.ts +7 -27
- package/src/showOutput/index.ts +6 -22
- package/src/sidebar/index.ts +20 -12
- package/src/terminalNotifications/index.ts +42 -25
- package/src/terminals/agentTerminals.ts +25 -49
- package/src/terminals/detection.ts +4 -8
- package/src/terminals/index.ts +12 -101
- package/src/terminals/model.ts +130 -246
- package/src/terminals/tokens.ts +11 -22
- package/src/terminals/widget.tsx +48 -31
- package/src/topBar/icons.ts +3 -8
- package/src/topBar/index.ts +21 -44
- package/src/walkthrough/index.ts +6 -20
- package/src/walkthrough/panel.ts +40 -10
- package/style/about.css +2 -7
- package/style/askAgent.css +8 -40
- package/style/base.css +9 -45
- package/style/chrome.css +108 -308
- package/style/commandBar.css +4 -20
- package/style/customPanel.css +1 -4
- package/style/git.css +26 -186
- package/style/highlight.css +1 -3
- package/style/launcher.css +6 -70
- package/style/omnibox.css +2 -14
- package/style/showOutput.css +0 -6
- package/style/sidebar.css +29 -9
- package/style/tabs.css +5 -13
- package/style/terminals.css +6 -53
- package/style/topBar.css +2 -22
- package/style/walkthrough.css +0 -8
package/src/git/tokens.ts
CHANGED
|
@@ -1,21 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Types shared by the git plugin
|
|
3
|
-
* `jupyterlab_git` server extension's REST API
|
|
4
|
-
* tightly coupled to a single version of those endpoints.
|
|
2
|
+
* Types shared by the git plugin, mirroring the response shapes of the
|
|
3
|
+
* `jupyterlab_git` server extension's REST API.
|
|
5
4
|
*/
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* git repository root, `from` is the source path for renames (and equal to
|
|
12
|
-
* `to` for any other status).
|
|
7
|
+
* One entry of the `files` array from `POST /git/<path>/status`. `x`/`y` are
|
|
8
|
+
* the porcelain index/worktree codes; `to` is the current repo-relative path
|
|
9
|
+
* and `from` the rename source (equal to `to` for any other status).
|
|
13
10
|
*/
|
|
14
11
|
export interface IGitStatusFile {
|
|
12
|
+
/**
|
|
13
|
+
* The porcelain status code for the index side.
|
|
14
|
+
*/
|
|
15
15
|
x: string;
|
|
16
|
+
/**
|
|
17
|
+
* The porcelain status code for the worktree side.
|
|
18
|
+
*/
|
|
16
19
|
y: string;
|
|
20
|
+
/**
|
|
21
|
+
* The current repo-relative path of the file.
|
|
22
|
+
*/
|
|
17
23
|
to: string;
|
|
24
|
+
/**
|
|
25
|
+
* The rename source path; equal to `to` for any other status.
|
|
26
|
+
*/
|
|
18
27
|
from: string;
|
|
28
|
+
/**
|
|
29
|
+
* Whether the file content is binary; `null` when undetermined.
|
|
30
|
+
*/
|
|
19
31
|
is_binary: boolean | null;
|
|
20
32
|
}
|
|
21
33
|
|
|
@@ -23,52 +35,68 @@ export interface IGitStatusFile {
|
|
|
23
35
|
* Response shape of `POST /git/<path>/status`.
|
|
24
36
|
*/
|
|
25
37
|
export interface IGitStatusResult {
|
|
38
|
+
/**
|
|
39
|
+
* The return code of the git command.
|
|
40
|
+
*/
|
|
26
41
|
code: number;
|
|
42
|
+
/**
|
|
43
|
+
* The current branch name; `null` when it is not available.
|
|
44
|
+
*/
|
|
27
45
|
branch: string | null;
|
|
46
|
+
/**
|
|
47
|
+
* The upstream remote branch; `null` when none is set.
|
|
48
|
+
*/
|
|
28
49
|
remote: string | null;
|
|
50
|
+
/**
|
|
51
|
+
* The number of commits ahead of the upstream branch.
|
|
52
|
+
*/
|
|
29
53
|
ahead: number;
|
|
54
|
+
/**
|
|
55
|
+
* The number of commits behind the upstream branch.
|
|
56
|
+
*/
|
|
30
57
|
behind: number;
|
|
58
|
+
/**
|
|
59
|
+
* The changed files reported by `git status`.
|
|
60
|
+
*/
|
|
31
61
|
files: IGitStatusFile[];
|
|
62
|
+
/**
|
|
63
|
+
* The in-progress repository state (merge, rebase, ...), when reported.
|
|
64
|
+
*/
|
|
32
65
|
state?: number;
|
|
66
|
+
/**
|
|
67
|
+
* An error message, present when the command fails.
|
|
68
|
+
*/
|
|
33
69
|
message?: string;
|
|
34
70
|
}
|
|
35
71
|
|
|
36
72
|
/**
|
|
37
|
-
* Reference accepted by `POST /git/<path>/content`
|
|
38
|
-
*
|
|
39
|
-
* copy, and a `git` value is any commit-ish (`HEAD`, a SHA, …).
|
|
73
|
+
* Reference accepted by `POST /git/<path>/content`: `WORKING` is the on-disk
|
|
74
|
+
* copy, `INDEX` the staged copy, `git` any commit-ish.
|
|
40
75
|
*/
|
|
41
76
|
export type GitReference =
|
|
42
77
|
| { special: 'WORKING' | 'INDEX' | 'BASE' }
|
|
43
78
|
| { git: string };
|
|
44
79
|
|
|
45
80
|
/**
|
|
46
|
-
* Response shape of `POST /git/<path>/content`.
|
|
47
|
-
* content here; binary files are reported as binary in the status response,
|
|
48
|
-
* and we surface them in the UI without attempting to render their diff.
|
|
81
|
+
* Response shape of `POST /git/<path>/content`.
|
|
49
82
|
*/
|
|
50
83
|
export interface IGitContentResult {
|
|
84
|
+
/**
|
|
85
|
+
* The return code of the git command.
|
|
86
|
+
*/
|
|
51
87
|
code: number;
|
|
88
|
+
/**
|
|
89
|
+
* The file content at the requested reference.
|
|
90
|
+
*/
|
|
52
91
|
content: string;
|
|
92
|
+
/**
|
|
93
|
+
* An error message, present when the command fails.
|
|
94
|
+
*/
|
|
53
95
|
message?: string;
|
|
54
96
|
}
|
|
55
97
|
|
|
56
|
-
/**
|
|
57
|
-
* Where a file's change lives relative to the index.
|
|
58
|
-
*
|
|
59
|
-
* - `staged` → present in the index, may differ from HEAD
|
|
60
|
-
* - `unstaged` → present in the worktree, differs from the index
|
|
61
|
-
*
|
|
62
|
-
* A single file can appear in both groups when the worktree has further
|
|
63
|
-
* changes on top of an already-staged version. The panel models that as two
|
|
64
|
-
* separate entries, one per group.
|
|
65
|
-
*/
|
|
66
98
|
type FileChangeGroup = 'staged' | 'unstaged';
|
|
67
99
|
|
|
68
|
-
/**
|
|
69
|
-
* The user-facing status of a file change. Drives the single-letter badge
|
|
70
|
-
* (M/A/D/R/U/?) shown next to each entry in the panel.
|
|
71
|
-
*/
|
|
72
100
|
export type FileChangeStatus =
|
|
73
101
|
| 'modified'
|
|
74
102
|
| 'added'
|
|
@@ -80,14 +108,28 @@ export type FileChangeStatus =
|
|
|
80
108
|
| 'unknown';
|
|
81
109
|
|
|
82
110
|
/**
|
|
83
|
-
* One row in the changes panel. `path` is
|
|
84
|
-
*
|
|
85
|
-
* case it carries the original path.
|
|
111
|
+
* One row in the changes panel. `path` is repo-relative; `from` is set only
|
|
112
|
+
* for renames and carries the original path.
|
|
86
113
|
*/
|
|
87
114
|
export interface IFileChange {
|
|
115
|
+
/**
|
|
116
|
+
* The repo-relative path of the file.
|
|
117
|
+
*/
|
|
88
118
|
path: string;
|
|
119
|
+
/**
|
|
120
|
+
* The rename source path, set only for renames.
|
|
121
|
+
*/
|
|
89
122
|
from?: string;
|
|
123
|
+
/**
|
|
124
|
+
* Whether the change is staged or unstaged.
|
|
125
|
+
*/
|
|
90
126
|
group: FileChangeGroup;
|
|
127
|
+
/**
|
|
128
|
+
* The change status derived from the porcelain codes.
|
|
129
|
+
*/
|
|
91
130
|
status: FileChangeStatus;
|
|
131
|
+
/**
|
|
132
|
+
* Whether the file content is binary; `null` when undetermined.
|
|
133
|
+
*/
|
|
92
134
|
isBinary: boolean | null;
|
|
93
135
|
}
|
package/src/highlight/index.ts
CHANGED
|
@@ -13,22 +13,13 @@ import type { Widget } from '@lumino/widgets';
|
|
|
13
13
|
|
|
14
14
|
const PLUGIN_ID = 'xtralab:highlight';
|
|
15
15
|
|
|
16
|
-
/**
|
|
17
|
-
* Highlight a contiguous range of lines, or clear every highlight. These are
|
|
18
|
-
* the only two commands the plugin contributes; both are designed to be driven
|
|
19
|
-
* by a coding agent over the MCP command bridge to walk a user through code.
|
|
20
|
-
*/
|
|
21
16
|
const HIGHLIGHT_LINES_COMMAND = 'xtralab:highlight-lines';
|
|
22
17
|
const CLEAR_HIGHLIGHTS_COMMAND = 'xtralab:clear-highlights';
|
|
23
18
|
|
|
24
|
-
/**
|
|
25
|
-
* CodeMirror line-decoration class; styled in style/highlight.css.
|
|
26
|
-
*/
|
|
27
19
|
const HIGHLIGHT_LINE_CLASS = 'jp-xtralab-highlightLine';
|
|
28
20
|
|
|
29
21
|
/**
|
|
30
|
-
*
|
|
31
|
-
* highlight, or `null` to clear the editor's highlights.
|
|
22
|
+
* Carries the 1-indexed inclusive line range to highlight, or `null` to clear.
|
|
32
23
|
*/
|
|
33
24
|
const setHighlight = StateEffect.define<{
|
|
34
25
|
start: number;
|
|
@@ -36,9 +27,8 @@ const setHighlight = StateEffect.define<{
|
|
|
36
27
|
} | null>();
|
|
37
28
|
|
|
38
29
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* editors that are never highlighted pay nothing.
|
|
30
|
+
* Highlight decorations for one editor; injected lazily via
|
|
31
|
+
* `StateEffect.appendConfig` so editors never highlighted pay nothing.
|
|
42
32
|
*/
|
|
43
33
|
const highlightField = StateField.define<DecorationSet>({
|
|
44
34
|
create: () => Decoration.none,
|
|
@@ -68,11 +58,6 @@ const highlightField = StateField.define<DecorationSet>({
|
|
|
68
58
|
provide: field => EditorView.decorations.from(field)
|
|
69
59
|
});
|
|
70
60
|
|
|
71
|
-
/**
|
|
72
|
-
* Return the CodeMirror view backing a widget's file editor, or `null` when
|
|
73
|
-
* the widget is not a CodeMirror-based text editor (a notebook, a terminal,
|
|
74
|
-
* the settings editor, …).
|
|
75
|
-
*/
|
|
76
61
|
function viewForWidget(widget: Widget | null): EditorView | null {
|
|
77
62
|
const content = (widget as { content?: unknown } | null)?.content;
|
|
78
63
|
return content instanceof FileEditor &&
|
|
@@ -81,26 +66,16 @@ function viewForWidget(widget: Widget | null): EditorView | null {
|
|
|
81
66
|
: null;
|
|
82
67
|
}
|
|
83
68
|
|
|
84
|
-
/**
|
|
85
|
-
* Coerce a JSON command argument to a positive integer line number, falling
|
|
86
|
-
* back to `fallback` when it is missing or not a finite number.
|
|
87
|
-
*/
|
|
88
69
|
function toLine(value: unknown, fallback: number): number {
|
|
89
70
|
const n = Math.trunc(Number(value));
|
|
90
71
|
return Number.isFinite(n) && n >= 1 ? n : fallback;
|
|
91
72
|
}
|
|
92
73
|
|
|
93
74
|
/**
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* highlight a span of lines — `documentsearch:start` only marks text matches
|
|
99
|
-
* and hijacks the find box. This plugin fills that gap with a CodeMirror line
|
|
100
|
-
* decoration, so an agent can point at "lines 31–43 of src/index.ts" while it
|
|
101
|
-
* narrates a walkthrough. `xtralab:highlight-lines` opens the file when needed,
|
|
102
|
-
* scrolls the range into view, and replaces any previous highlight in that
|
|
103
|
-
* editor; `xtralab:clear-highlights` removes every highlight.
|
|
75
|
+
* Contributes `xtralab:highlight-lines` and `xtralab:clear-highlights`,
|
|
76
|
+
* filling the persistent span-highlight gap in the core command surface
|
|
77
|
+
* (`documentsearch:start` only marks text matches and hijacks the find box)
|
|
78
|
+
* so an agent can point at lines while narrating a walkthrough.
|
|
104
79
|
*/
|
|
105
80
|
const plugin: JupyterFrontEndPlugin<void> = {
|
|
106
81
|
id: PLUGIN_ID,
|
|
@@ -117,8 +92,6 @@ const plugin: JupyterFrontEndPlugin<void> = {
|
|
|
117
92
|
const { commands, shell } = app;
|
|
118
93
|
const trans = (translator ?? nullTranslator).load('jupyterlab');
|
|
119
94
|
|
|
120
|
-
// Editors that currently carry a highlight, so a single clear can reach
|
|
121
|
-
// them all. Disposed editors are dropped on the next clear.
|
|
122
95
|
const highlighted = new Set<EditorView>();
|
|
123
96
|
|
|
124
97
|
const ensureField = (view: EditorView): void => {
|
|
@@ -130,8 +103,7 @@ const plugin: JupyterFrontEndPlugin<void> = {
|
|
|
130
103
|
commands.addCommand(HIGHLIGHT_LINES_COMMAND, {
|
|
131
104
|
label: trans.__('Highlight Lines'),
|
|
132
105
|
caption: trans.__('Highlight a range of lines in a text editor'),
|
|
133
|
-
// Advertise the argument shape
|
|
134
|
-
// bridge can see how to call it, the same way core commands do.
|
|
106
|
+
// Advertise the argument shape to agents listing commands over the MCP bridge.
|
|
135
107
|
describedBy: {
|
|
136
108
|
args: {
|
|
137
109
|
type: 'object',
|
|
@@ -165,9 +137,8 @@ const plugin: JupyterFrontEndPlugin<void> = {
|
|
|
165
137
|
typeof args['path'] === 'string' ? args['path'] : undefined;
|
|
166
138
|
const reveal = args['reveal'] !== false;
|
|
167
139
|
|
|
168
|
-
// With a path, bind strictly to that document
|
|
169
|
-
// active widget
|
|
170
|
-
// unrelated editor that happens to be focused.
|
|
140
|
+
// With a path, bind strictly to that document — falling back to the
|
|
141
|
+
// active widget could silently highlight an unrelated editor.
|
|
171
142
|
let widget: Widget | null;
|
|
172
143
|
if (path) {
|
|
173
144
|
// Fail fast on a missing path instead of opening a phantom widget
|
|
@@ -181,7 +152,6 @@ const plugin: JupyterFrontEndPlugin<void> = {
|
|
|
181
152
|
if (!opened) {
|
|
182
153
|
throw new Error(`xtralab: could not open "${path}"`);
|
|
183
154
|
}
|
|
184
|
-
// Wait for the model and the editor view to be ready.
|
|
185
155
|
await opened.context.ready;
|
|
186
156
|
await opened.revealed;
|
|
187
157
|
widget = opened;
|
|
@@ -213,7 +183,6 @@ const plugin: JupyterFrontEndPlugin<void> = {
|
|
|
213
183
|
effects.push(EditorView.scrollIntoView(anchor, { y: 'center' }));
|
|
214
184
|
}
|
|
215
185
|
view.dispatch({ effects });
|
|
216
|
-
// Forget editors that have since been closed before tracking this one.
|
|
217
186
|
for (const tracked of highlighted) {
|
|
218
187
|
if (!tracked.dom.isConnected) {
|
|
219
188
|
highlighted.delete(tracked);
|
package/src/index.ts
CHANGED
|
@@ -23,15 +23,6 @@ import terminalsPlugin from './terminals';
|
|
|
23
23
|
import topBarPlugin from './topBar';
|
|
24
24
|
import walkthroughPlugin from './walkthrough';
|
|
25
25
|
|
|
26
|
-
/**
|
|
27
|
-
* Every plugin contributed by `xtralab`. The entry point of the
|
|
28
|
-
* labextension is an array because the package bundles several independent
|
|
29
|
-
* enhancements (file browser, git diff providers, …) — JupyterLab activates
|
|
30
|
-
* each plugin individually and only the ones whose required tokens are
|
|
31
|
-
* available end up running. `gitPlugins` and `launcherPlugins` are themselves
|
|
32
|
-
* arrays (the git diff providers; the launcher plus its editor registry), so
|
|
33
|
-
* they are spread in.
|
|
34
|
-
*/
|
|
35
26
|
const plugins: JupyterFrontEndPlugin<unknown>[] = [
|
|
36
27
|
aboutPlugin,
|
|
37
28
|
agentSessionsPlugin,
|
package/src/launcher/agents.ts
CHANGED
|
@@ -3,92 +3,98 @@ import { LabIcon, terminalIcon } from '@jupyterlab/ui-components';
|
|
|
3
3
|
import { BUILTIN_AGENT_ICONS } from './icons';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* aliases, so users can point at `claude`, `cl`, or whatever runs their
|
|
9
|
-
* preferred wrapper.
|
|
6
|
+
* An agent card on the launcher. `command` is the literal text typed into the
|
|
7
|
+
* new terminal, so interactive-shell aliases resolve.
|
|
10
8
|
*/
|
|
11
9
|
export interface IAgent {
|
|
10
|
+
/**
|
|
11
|
+
* Stable id; keys the settings merge and the per-agent launch command.
|
|
12
|
+
*/
|
|
12
13
|
id: string;
|
|
14
|
+
/**
|
|
15
|
+
* Card label, e.g. "Claude".
|
|
16
|
+
*/
|
|
13
17
|
label: string;
|
|
18
|
+
/**
|
|
19
|
+
* Card tooltip; also the palette command caption.
|
|
20
|
+
*/
|
|
14
21
|
caption: string;
|
|
22
|
+
/**
|
|
23
|
+
* The literal command typed into the new terminal.
|
|
24
|
+
*/
|
|
15
25
|
command: string;
|
|
26
|
+
/**
|
|
27
|
+
* Brand icon for the card.
|
|
28
|
+
*/
|
|
16
29
|
icon: LabIcon;
|
|
30
|
+
/**
|
|
31
|
+
* Sort position among the launcher's agent cards.
|
|
32
|
+
*/
|
|
17
33
|
rank: number;
|
|
18
34
|
/**
|
|
19
|
-
* When false,
|
|
20
|
-
*
|
|
21
|
-
* but still resolve when typed in a real terminal. Defaults to true.
|
|
35
|
+
* When false, skip the `which`-based availability check — for aliases or
|
|
36
|
+
* shell functions not on PATH. Defaults to true.
|
|
22
37
|
*/
|
|
23
38
|
requireAvailable: boolean;
|
|
24
39
|
/**
|
|
25
|
-
* Argv tokens spliced between `command` and
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* - `[]` → prompt is appended as a positional argument:
|
|
29
|
-
* `<command> 'PROMPT'`. (Used by claude, codex, vibe, pi.)
|
|
30
|
-
* - `['-i']` / `['--prompt']` → the prompt is preceded by a flag:
|
|
31
|
-
* `<command> -i 'PROMPT'`. (Used by copilot, opencode.)
|
|
32
|
-
* - `undefined` → the agent does not accept an initial prompt. The
|
|
33
|
-
* launcher dims the agent's button while the prompt textarea is
|
|
34
|
-
* non-empty, so the user gets a clear signal rather than a silently
|
|
35
|
-
* dropped prompt.
|
|
36
|
-
*
|
|
37
|
-
* The prompt itself is always single-quoted with embedded single quotes
|
|
38
|
-
* escaped, so multi-line prompts and shell metacharacters are safe.
|
|
40
|
+
* Argv tokens spliced between `command` and the shell-quoted prompt:
|
|
41
|
+
* `[]` appends the prompt positionally, `['-i']` prefixes a flag, and
|
|
42
|
+
* `undefined` means no prompt support (the launcher dims the button).
|
|
39
43
|
*/
|
|
40
44
|
promptArgs?: string[];
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
/**
|
|
44
|
-
* The settings-side shape: every field except `id` is optional
|
|
45
|
-
*
|
|
46
|
-
* an alias) without restating the whole entry. New ids define brand-new
|
|
47
|
-
* agent cards.
|
|
48
|
+
* The settings-side shape: every field except `id` is optional so a user can
|
|
49
|
+
* override a single field on a default agent; new ids define new agent cards.
|
|
48
50
|
*/
|
|
49
51
|
export interface IAgentSettings {
|
|
52
|
+
/**
|
|
53
|
+
* Id of the agent to override; a new id defines a new card.
|
|
54
|
+
*/
|
|
50
55
|
id: string;
|
|
56
|
+
/**
|
|
57
|
+
* See `IAgent.label`.
|
|
58
|
+
*/
|
|
51
59
|
label?: string;
|
|
60
|
+
/**
|
|
61
|
+
* See `IAgent.caption`.
|
|
62
|
+
*/
|
|
52
63
|
caption?: string;
|
|
64
|
+
/**
|
|
65
|
+
* See `IAgent.command`.
|
|
66
|
+
*/
|
|
53
67
|
command?: string;
|
|
54
68
|
/**
|
|
55
|
-
* Inline SVG
|
|
56
|
-
*
|
|
57
|
-
* set (in which case it overrides the built-in).
|
|
69
|
+
* Inline SVG icon. Required for new ids; overrides the built-in when set on
|
|
70
|
+
* a default id.
|
|
58
71
|
*/
|
|
59
72
|
iconSvg?: string;
|
|
73
|
+
/**
|
|
74
|
+
* See `IAgent.rank`.
|
|
75
|
+
*/
|
|
60
76
|
rank?: number;
|
|
61
77
|
/**
|
|
62
|
-
* When false, the agent
|
|
63
|
-
* palette. Defaults to true.
|
|
78
|
+
* When false, hides the agent from the launcher and the command palette.
|
|
64
79
|
*/
|
|
65
80
|
enabled?: boolean;
|
|
66
81
|
/**
|
|
67
|
-
* See `IAgent.requireAvailable`. Defaults to true
|
|
68
|
-
*
|
|
69
|
-
* `command` (a user-chosen command — often a shell alias — is trusted and
|
|
70
|
-
* always shown). Set it explicitly to force the check on or off.
|
|
82
|
+
* See `IAgent.requireAvailable`. Defaults to true, but flips to false once
|
|
83
|
+
* `command` is overridden (a user-chosen alias is trusted).
|
|
71
84
|
*/
|
|
72
85
|
requireAvailable?: boolean;
|
|
73
86
|
/**
|
|
74
|
-
* See `IAgent.promptArgs`.
|
|
75
|
-
*
|
|
76
|
-
* flag. Pass `null` to explicitly turn off prompt support for an agent
|
|
77
|
-
* that has it on by default.
|
|
87
|
+
* See `IAgent.promptArgs`. `null` explicitly turns off an agent's default
|
|
88
|
+
* prompt support.
|
|
78
89
|
*/
|
|
79
90
|
promptArgs?: string[] | null;
|
|
80
91
|
}
|
|
81
92
|
|
|
82
93
|
/**
|
|
83
|
-
* Default agent cards
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* terminal rather than the ACP wrapper binaries that project spawns.
|
|
88
|
-
* Antigravity (Google's agent-first IDE/CLI, `agy`) is the Google agent.
|
|
89
|
-
* Pi (https://pi.dev, `earendil-works/pi`) is a minimal extensible coding
|
|
90
|
-
* agent; its mark comes straight from its site. Anything not on the user's
|
|
91
|
-
* `$PATH` is filtered out at activation time, so the wider list is harmless.
|
|
94
|
+
* Default agent cards. Most mirror `jupyter-ai-contrib/jupyter-ai-acp-client`
|
|
95
|
+
* personas but use the bare CLI names a user would type, not the ACP wrappers.
|
|
96
|
+
* Anything not on `$PATH` is filtered out at activation, so the wide list is
|
|
97
|
+
* harmless.
|
|
92
98
|
*/
|
|
93
99
|
const DEFAULTS: IAgent[] = [
|
|
94
100
|
{
|
|
@@ -119,13 +125,8 @@ const DEFAULTS: IAgent[] = [
|
|
|
119
125
|
icon: BUILTIN_AGENT_ICONS.antigravity,
|
|
120
126
|
rank: 2,
|
|
121
127
|
requireAvailable: true
|
|
122
|
-
// `agy`
|
|
123
|
-
//
|
|
124
|
-
// Its positional args are file/folder paths, so there is no inline
|
|
125
|
-
// natural-language prompt form; like goose/kiro we omit promptArgs so a
|
|
126
|
-
// typed prompt dims the button instead of being mangled into a path.
|
|
127
|
-
// The command stays the bare binary (no `agy .`) so the server-side
|
|
128
|
-
// `shutil.which` availability check still resolves it.
|
|
128
|
+
// `agy` opens the Antigravity editor; its positional args are paths, not
|
|
129
|
+
// prompts, and the bare binary keeps the server-side `which` check working.
|
|
129
130
|
},
|
|
130
131
|
{
|
|
131
132
|
id: 'copilot',
|
|
@@ -135,8 +136,7 @@ const DEFAULTS: IAgent[] = [
|
|
|
135
136
|
icon: BUILTIN_AGENT_ICONS.copilot,
|
|
136
137
|
rank: 3,
|
|
137
138
|
requireAvailable: true,
|
|
138
|
-
// `-i
|
|
139
|
-
// auto-execute the prompt; `-p` exits after responding (non-interactive).
|
|
139
|
+
// `-i` starts interactive mode with the prompt; `-p` exits after responding.
|
|
140
140
|
promptArgs: ['-i']
|
|
141
141
|
},
|
|
142
142
|
{
|
|
@@ -147,8 +147,7 @@ const DEFAULTS: IAgent[] = [
|
|
|
147
147
|
icon: BUILTIN_AGENT_ICONS.goose,
|
|
148
148
|
rank: 4,
|
|
149
149
|
requireAvailable: true
|
|
150
|
-
// `goose`
|
|
151
|
-
// need to type the prompt after `goose session` starts.
|
|
150
|
+
// `goose` takes no inline prompt; it must be typed after `goose session`.
|
|
152
151
|
},
|
|
153
152
|
{
|
|
154
153
|
id: 'opencode',
|
|
@@ -168,8 +167,7 @@ const DEFAULTS: IAgent[] = [
|
|
|
168
167
|
icon: BUILTIN_AGENT_ICONS.kiro,
|
|
169
168
|
rank: 6,
|
|
170
169
|
requireAvailable: true
|
|
171
|
-
//
|
|
172
|
-
// `/chat new <prompt>` slash command, not a CLI argument.
|
|
170
|
+
// Kiro only takes initial prompts via the in-session `/chat new` command.
|
|
173
171
|
},
|
|
174
172
|
{
|
|
175
173
|
id: 'mistral-vibe',
|
|
@@ -189,17 +187,13 @@ const DEFAULTS: IAgent[] = [
|
|
|
189
187
|
icon: BUILTIN_AGENT_ICONS.pi,
|
|
190
188
|
rank: 8,
|
|
191
189
|
requireAvailable: true,
|
|
192
|
-
// `pi [messages...]` starts the interactive TUI and sends the messages
|
|
193
|
-
// as the first user prompt, so the positional form applies.
|
|
194
190
|
promptArgs: []
|
|
195
191
|
}
|
|
196
192
|
];
|
|
197
193
|
|
|
198
194
|
/**
|
|
199
|
-
* The built-in agents projected into the
|
|
200
|
-
*
|
|
201
|
-
* {@link registerLauncherSchemaDefaults} injects this as the `agents` setting's
|
|
202
|
-
* schema default so the Settings Editor shows the shipped list.
|
|
195
|
+
* The built-in agents projected into the settings shape (no runtime LabIcon),
|
|
196
|
+
* injected as the `agents` schema default so the Settings Editor shows them.
|
|
203
197
|
*/
|
|
204
198
|
export function defaultAgentSettings(): IAgentSettings[] {
|
|
205
199
|
return DEFAULTS.map(agent => {
|
|
@@ -211,8 +205,6 @@ export function defaultAgentSettings(): IAgentSettings[] {
|
|
|
211
205
|
rank: agent.rank,
|
|
212
206
|
requireAvailable: agent.requireAvailable
|
|
213
207
|
};
|
|
214
|
-
// Omit `promptArgs` for agents that don't take an inline prompt, so the
|
|
215
|
-
// default doesn't show a prompt form they lack.
|
|
216
208
|
if (agent.promptArgs !== undefined) {
|
|
217
209
|
entry.promptArgs = agent.promptArgs;
|
|
218
210
|
}
|
|
@@ -228,15 +220,10 @@ function resolveIcon(id: string, iconSvg: string | undefined): LabIcon {
|
|
|
228
220
|
}
|
|
229
221
|
|
|
230
222
|
/**
|
|
231
|
-
* Merge xtralab's defaults with the user's settings
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
* Overriding a built-in agent's `command` also turns its `requireAvailable`
|
|
237
|
-
* off, so the card survives the launcher's `which`-based availability filter
|
|
238
|
-
* even when the new command is a shell alias the server can't resolve. See the
|
|
239
|
-
* built-in branch below for the rationale.
|
|
223
|
+
* Merge xtralab's defaults with the user's settings: defaults keep their
|
|
224
|
+
* fields unless overridden, user-only ids are appended, and `enabled: false`
|
|
225
|
+
* removes an entry entirely. Overriding a built-in's `command` also turns
|
|
226
|
+
* `requireAvailable` off so an aliased command survives the `which` filter.
|
|
240
227
|
*/
|
|
241
228
|
export function mergeAgents(overrides: IAgentSettings[]): IAgent[] {
|
|
242
229
|
const overrideById = new Map(overrides.map(entry => [entry.id, entry]));
|
|
@@ -262,24 +249,10 @@ export function mergeAgents(overrides: IAgentSettings[]): IAgent[] {
|
|
|
262
249
|
? resolveIcon(base.id, override.iconSvg)
|
|
263
250
|
: base.icon,
|
|
264
251
|
rank: override.rank ?? base.rank,
|
|
265
|
-
// The availability filter exists to prune xtralab's *built-in* command
|
|
266
|
-
// from the launcher when it isn't installed. Once the user points the
|
|
267
|
-
// agent at their own command — e.g. the `ccm` alias wrapping `claude
|
|
268
|
-
// --effort=max …` — the server's `shutil.which` probe can't see it
|
|
269
|
-
// (aliases and shell functions only exist inside an interactive shell),
|
|
270
|
-
// so keeping the check on would wrongly hide the card. We therefore only
|
|
271
|
-
// require availability while the command is still xtralab's default; a
|
|
272
|
-
// user-chosen command is trusted and always shown. An explicit
|
|
273
|
-
// `requireAvailable` still applies to the unchanged default command, so a
|
|
274
|
-
// user can alias `claude` itself and set `requireAvailable: false` (or
|
|
275
|
-
// force the check back on).
|
|
276
252
|
requireAvailable:
|
|
277
253
|
command === base.command
|
|
278
254
|
? (override.requireAvailable ?? base.requireAvailable)
|
|
279
255
|
: false,
|
|
280
|
-
// `null` is the explicit way to opt out of an agent's default prompt
|
|
281
|
-
// support; an absent key keeps the default. `undefined` from `??` is
|
|
282
|
-
// pruned below.
|
|
283
256
|
promptArgs:
|
|
284
257
|
override.promptArgs === null
|
|
285
258
|
? undefined
|
|
@@ -287,10 +260,6 @@ export function mergeAgents(overrides: IAgentSettings[]): IAgent[] {
|
|
|
287
260
|
});
|
|
288
261
|
}
|
|
289
262
|
|
|
290
|
-
// What remains in `overrideById` are entries with ids that don't match a
|
|
291
|
-
// default — treat them as new agents the user is adding. Skip silently
|
|
292
|
-
// when a required field is missing rather than throwing; the settings
|
|
293
|
-
// schema validates the shape, so this is just a defensive fallback.
|
|
294
263
|
let nextRank =
|
|
295
264
|
merged.reduce((max, agent) => Math.max(max, agent.rank), -1) + 1;
|
|
296
265
|
for (const entry of overrideById.values()) {
|
|
@@ -2,15 +2,9 @@ import { URLExt } from '@jupyterlab/coreutils';
|
|
|
2
2
|
import { ServerConnection } from '@jupyterlab/services';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* agent cards.
|
|
9
|
-
*
|
|
10
|
-
* On any failure (server extension not loaded, network error, malformed
|
|
11
|
-
* response) the returned Set is `null` — callers should treat that as
|
|
12
|
-
* "availability unknown" and either fall back to showing all agents or
|
|
13
|
-
* surface the error, depending on context.
|
|
5
|
+
* Ask the server extension's `which`-proxy endpoint which commands resolve on
|
|
6
|
+
* its `$PATH`. Returns `null` on any failure — callers should treat that as
|
|
7
|
+
* "availability unknown", not as "nothing available".
|
|
14
8
|
*/
|
|
15
9
|
export async function fetchAvailableCommands(
|
|
16
10
|
commands: string[]
|