xtralab 0.15.0 → 0.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -30
- package/lib/about/icons.d.ts +0 -5
- package/lib/about/icons.js +0 -5
- package/lib/about/index.d.ts +4 -8
- package/lib/about/index.js +6 -17
- package/lib/agentSessions.d.ts +9 -29
- package/lib/agentSessions.js +2 -7
- package/lib/askAgent/editorSelection.d.ts +20 -26
- package/lib/askAgent/editorSelection.js +11 -26
- package/lib/askAgent/icons.d.ts +2 -3
- package/lib/askAgent/icons.js +2 -3
- package/lib/askAgent/index.d.ts +4 -26
- package/lib/askAgent/index.js +54 -158
- package/lib/askAgent/popup.d.ts +12 -16
- package/lib/askAgent/popup.js +18 -37
- package/lib/askAgent/prompt.d.ts +3 -5
- package/lib/askAgent/prompt.js +6 -19
- package/lib/askAgent/queue.d.ts +11 -21
- package/lib/askAgent/queue.js +9 -19
- package/lib/askAgent/queuePanel.d.ts +13 -18
- package/lib/askAgent/queuePanel.js +15 -37
- package/lib/askAgent/targetPicker.d.ts +2 -9
- package/lib/askAgent/targetPicker.js +6 -11
- package/lib/askAgent/tokens.d.ts +32 -46
- package/lib/askAgent/tokens.js +4 -6
- package/lib/commandBar/index.d.ts +4 -13
- package/lib/commandBar/index.js +21 -39
- package/lib/customPanel/index.js +15 -0
- package/lib/editorBreadcrumbs/index.d.ts +3 -6
- package/lib/editorBreadcrumbs/index.js +10 -6
- package/lib/editorBreadcrumbs/widget.d.ts +17 -4
- package/lib/editorBreadcrumbs/widget.js +11 -17
- package/lib/editorIndent/index.d.ts +4 -12
- package/lib/editorIndent/index.js +8 -23
- package/lib/fileBrowser/commands.d.ts +29 -19
- package/lib/fileBrowser/commands.js +83 -97
- package/lib/fileBrowser/contents.d.ts +3 -0
- package/lib/fileBrowser/dragAndDrop.d.ts +17 -4
- package/lib/fileBrowser/dragAndDrop.js +2 -7
- package/lib/fileBrowser/fileBrowser.d.ts +19 -9
- package/lib/fileBrowser/fileBrowser.js +70 -222
- package/lib/fileBrowser/gitStatus.d.ts +16 -10
- package/lib/fileBrowser/gitStatus.js +31 -30
- package/lib/fileBrowser/gitignore.d.ts +4 -17
- package/lib/fileBrowser/gitignore.js +4 -25
- package/lib/fileBrowser/icons.d.ts +7 -17
- package/lib/fileBrowser/icons.js +25 -80
- package/lib/fileBrowser/index.js +2 -4
- package/lib/fileBrowser/widget.d.ts +141 -48
- package/lib/fileBrowser/widget.js +102 -4
- package/lib/fileTypeIcons/index.js +0 -10
- package/lib/git/api.d.ts +5 -13
- package/lib/git/api.js +10 -36
- package/lib/git/askRequest.d.ts +4 -8
- package/lib/git/askRequest.js +6 -20
- package/lib/git/commands.d.ts +45 -5
- package/lib/git/commands.js +20 -13
- package/lib/git/diffModel.js +4 -0
- package/lib/git/diffPreferences.d.ts +90 -0
- package/lib/git/diffPreferences.js +107 -0
- package/lib/git/diffProvider.js +10 -2
- package/lib/git/diffSurface.d.ts +64 -63
- package/lib/git/diffSurface.js +72 -213
- package/lib/git/diffTheme.d.ts +7 -0
- package/lib/git/diffTheme.js +23 -0
- package/lib/git/diffWidget.d.ts +70 -14
- package/lib/git/diffWidget.js +100 -94
- package/lib/git/imageDiff.d.ts +14 -6
- package/lib/git/imageDiff.js +19 -75
- package/lib/git/index.d.ts +0 -3
- package/lib/git/index.js +44 -10
- package/lib/git/notebookDiff.d.ts +110 -33
- package/lib/git/notebookDiff.js +55 -197
- package/lib/git/tokens.d.ts +73 -31
- package/lib/git/tokens.js +2 -3
- package/lib/highlight/index.d.ts +4 -10
- package/lib/highlight/index.js +10 -41
- package/lib/index.d.ts +0 -9
- package/lib/index.js +0 -9
- package/lib/launcher/agents.d.ts +55 -51
- package/lib/launcher/agents.js +15 -57
- package/lib/launcher/availability.d.ts +3 -9
- package/lib/launcher/availability.js +3 -9
- package/lib/launcher/commands.d.ts +7 -32
- package/lib/launcher/commands.js +14 -45
- package/lib/launcher/dashboard.d.ts +19 -24
- package/lib/launcher/dashboard.js +21 -67
- package/lib/launcher/editorRegistry.d.ts +10 -22
- package/lib/launcher/editorRegistry.js +14 -18
- package/lib/launcher/editors.d.ts +39 -45
- package/lib/launcher/editors.js +8 -34
- package/lib/launcher/icons.d.ts +0 -12
- package/lib/launcher/icons.js +5 -39
- package/lib/launcher/index.js +12 -55
- package/lib/launcher/invocation.d.ts +4 -10
- package/lib/launcher/invocation.js +7 -22
- package/lib/launcher/registry.d.ts +9 -7
- package/lib/launcher/registry.js +9 -7
- package/lib/launcher/tokens.d.ts +10 -22
- package/lib/launcher/tokens.js +5 -8
- package/lib/menuBar/index.d.ts +3 -10
- package/lib/menuBar/index.js +11 -28
- package/lib/menus/index.d.ts +3 -9
- package/lib/menus/index.js +14 -30
- package/lib/omnibox/files.d.ts +2 -4
- package/lib/omnibox/files.js +5 -11
- package/lib/omnibox/index.d.ts +4 -14
- package/lib/omnibox/index.js +9 -27
- package/lib/omnibox/model.d.ts +38 -10
- package/lib/omnibox/model.js +15 -33
- package/lib/omnibox/recents.d.ts +15 -17
- package/lib/omnibox/recents.js +12 -17
- package/lib/omnibox/tokens.d.ts +5 -10
- package/lib/omnibox/tokens.js +2 -6
- package/lib/omnibox/widget.d.ts +11 -7
- package/lib/omnibox/widget.js +8 -16
- package/lib/searchReplace/index.d.ts +4 -20
- package/lib/searchReplace/index.js +7 -27
- package/lib/showOutput/index.d.ts +3 -12
- package/lib/showOutput/index.js +6 -22
- package/lib/sidebar/index.d.ts +4 -7
- package/lib/sidebar/index.js +5 -12
- package/lib/terminalNotifications/index.d.ts +4 -10
- package/lib/terminalNotifications/index.js +6 -20
- package/lib/terminals/agentTerminals.d.ts +12 -5
- package/lib/terminals/agentTerminals.js +25 -44
- package/lib/terminals/detection.d.ts +4 -8
- package/lib/terminals/detection.js +4 -8
- package/lib/terminals/index.d.ts +0 -35
- package/lib/terminals/index.js +12 -101
- package/lib/terminals/model.d.ts +64 -139
- package/lib/terminals/model.js +80 -220
- package/lib/terminals/tokens.d.ts +11 -22
- package/lib/terminals/tokens.js +2 -2
- package/lib/terminals/widget.d.ts +43 -13
- package/lib/terminals/widget.js +33 -18
- package/lib/topBar/icons.d.ts +3 -8
- package/lib/topBar/icons.js +3 -8
- package/lib/topBar/index.d.ts +4 -11
- package/lib/topBar/index.js +10 -38
- package/lib/walkthrough/index.d.ts +4 -9
- package/lib/walkthrough/index.js +6 -20
- package/lib/walkthrough/panel.d.ts +40 -9
- package/lib/walkthrough/panel.js +4 -10
- package/package.json +5 -3
- package/schema/git-diff-preferences.json +42 -0
- package/src/about/icons.ts +0 -5
- package/src/about/index.tsx +6 -17
- package/src/agentSessions.ts +9 -29
- package/src/askAgent/editorSelection.ts +22 -29
- package/src/askAgent/icons.ts +2 -3
- package/src/askAgent/index.ts +54 -158
- package/src/askAgent/popup.tsx +23 -45
- package/src/askAgent/prompt.ts +6 -19
- package/src/askAgent/queue.ts +13 -24
- package/src/askAgent/queuePanel.tsx +21 -46
- package/src/askAgent/targetPicker.tsx +5 -15
- package/src/askAgent/tokens.ts +32 -46
- package/src/commandBar/index.ts +24 -39
- package/src/customPanel/index.ts +15 -0
- package/src/editorBreadcrumbs/index.ts +10 -6
- package/src/editorBreadcrumbs/widget.ts +23 -17
- package/src/editorIndent/index.ts +17 -23
- package/src/fileBrowser/commands.ts +119 -96
- package/src/fileBrowser/contents.ts +3 -0
- package/src/fileBrowser/dragAndDrop.ts +17 -7
- package/src/fileBrowser/fileBrowser.tsx +86 -230
- package/src/fileBrowser/gitStatus.ts +36 -33
- package/src/fileBrowser/gitignore.ts +4 -25
- package/src/fileBrowser/icons.ts +25 -80
- package/src/fileBrowser/index.ts +2 -4
- package/src/fileBrowser/widget.tsx +171 -50
- package/src/fileTypeIcons/index.ts +0 -10
- package/src/git/api.ts +10 -36
- package/src/git/askRequest.ts +6 -20
- package/src/git/commands.ts +83 -11
- package/src/git/diffModel.ts +25 -0
- package/src/git/diffPreferences.ts +192 -0
- package/src/git/diffProvider.tsx +11 -2
- package/src/git/diffSurface.tsx +165 -286
- package/src/git/diffTheme.ts +24 -0
- package/src/git/diffWidget.tsx +194 -134
- package/src/git/imageDiff.tsx +56 -84
- package/src/git/index.ts +54 -10
- package/src/git/notebookDiff.tsx +214 -240
- package/src/git/tokens.ts +73 -31
- package/src/highlight/index.ts +10 -41
- package/src/index.ts +0 -9
- package/src/launcher/agents.ts +64 -95
- package/src/launcher/availability.ts +3 -9
- package/src/launcher/commands.ts +14 -51
- package/src/launcher/dashboard.tsx +49 -88
- package/src/launcher/editorRegistry.ts +21 -29
- package/src/launcher/editors.ts +39 -58
- package/src/launcher/icons.ts +5 -39
- package/src/launcher/index.ts +12 -55
- package/src/launcher/invocation.ts +7 -22
- package/src/launcher/registry.ts +9 -7
- package/src/launcher/tokens.ts +10 -22
- package/src/menuBar/index.ts +11 -28
- package/src/menus/index.ts +14 -30
- package/src/omnibox/files.ts +10 -14
- package/src/omnibox/index.ts +9 -27
- package/src/omnibox/model.ts +50 -38
- package/src/omnibox/recents.ts +17 -22
- package/src/omnibox/tokens.ts +5 -10
- package/src/omnibox/widget.tsx +14 -19
- package/src/searchReplace/index.ts +7 -27
- package/src/showOutput/index.ts +6 -22
- package/src/sidebar/index.ts +20 -12
- package/src/terminalNotifications/index.ts +42 -25
- package/src/terminals/agentTerminals.ts +25 -49
- package/src/terminals/detection.ts +4 -8
- package/src/terminals/index.ts +12 -101
- package/src/terminals/model.ts +130 -246
- package/src/terminals/tokens.ts +11 -22
- package/src/terminals/widget.tsx +48 -31
- package/src/topBar/icons.ts +3 -8
- package/src/topBar/index.ts +21 -44
- package/src/walkthrough/index.ts +6 -20
- package/src/walkthrough/panel.ts +40 -10
- package/style/about.css +2 -7
- package/style/askAgent.css +8 -40
- package/style/base.css +9 -45
- package/style/chrome.css +108 -308
- package/style/commandBar.css +4 -20
- package/style/customPanel.css +1 -4
- package/style/git.css +26 -186
- package/style/highlight.css +1 -3
- package/style/launcher.css +6 -70
- package/style/omnibox.css +2 -14
- package/style/showOutput.css +0 -6
- package/style/sidebar.css +29 -9
- package/style/tabs.css +5 -13
- package/style/terminals.css +6 -53
- package/style/topBar.css +2 -22
- package/style/walkthrough.css +0 -8
package/lib/askAgent/prompt.js
CHANGED
|
@@ -10,10 +10,8 @@ export function serverPath(context) {
|
|
|
10
10
|
: context.path;
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
|
-
* Cap on the
|
|
14
|
-
*
|
|
15
|
-
* themselves — so a very long selection is trimmed instead of being typed
|
|
16
|
-
* into the terminal wholesale.
|
|
13
|
+
* Cap on the embedded snippet; the path and line range are the
|
|
14
|
+
* authoritative pointers, so a very long selection is trimmed.
|
|
17
15
|
*/
|
|
18
16
|
const MAX_SNIPPET_CHARS = 2000;
|
|
19
17
|
/**
|
|
@@ -28,10 +26,6 @@ function fenceFor(text) {
|
|
|
28
26
|
}
|
|
29
27
|
return '`'.repeat(Math.max(3, longest + 1));
|
|
30
28
|
}
|
|
31
|
-
/**
|
|
32
|
-
* Trim `text` to {@link MAX_SNIPPET_CHARS}, cutting at a line boundary.
|
|
33
|
-
* Returns the (possibly shortened) snippet and whether anything was dropped.
|
|
34
|
-
*/
|
|
35
29
|
function clampSnippet(text) {
|
|
36
30
|
if (text.length <= MAX_SNIPPET_CHARS) {
|
|
37
31
|
return { snippet: text, truncated: false };
|
|
@@ -53,7 +47,7 @@ function locatorFor(context) {
|
|
|
53
47
|
const where = [`\`${context.path}\``];
|
|
54
48
|
if (context.cell !== undefined) {
|
|
55
49
|
// Both orderings so the agent can count cells or index the nbformat
|
|
56
|
-
// `cells` array
|
|
50
|
+
// `cells` array.
|
|
57
51
|
where.push(`${context.cell.type} cell ${context.cell.index + 1} ` +
|
|
58
52
|
`(0-based index ${context.cell.index})`);
|
|
59
53
|
}
|
|
@@ -69,11 +63,6 @@ function locatorFor(context) {
|
|
|
69
63
|
}
|
|
70
64
|
return where.join(', ');
|
|
71
65
|
}
|
|
72
|
-
/**
|
|
73
|
-
* The blocks describing one comment: `headline`, the selected snippet in a
|
|
74
|
-
* code fence (when there is one), then the user's instruction. Blocks are
|
|
75
|
-
* joined with blank lines by the callers.
|
|
76
|
-
*/
|
|
77
66
|
function commentParts(context, instruction, headline) {
|
|
78
67
|
const parts = [headline];
|
|
79
68
|
if (context.text.length > 0) {
|
|
@@ -88,11 +77,9 @@ function commentParts(context, instruction, headline) {
|
|
|
88
77
|
return parts;
|
|
89
78
|
}
|
|
90
79
|
/**
|
|
91
|
-
* Compose the prompt handed to the agent CLI:
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
* The scaffold is written in English on purpose — it is consumed by the
|
|
95
|
-
* agent, not shown in the UI, and the agent CLIs are English-first.
|
|
80
|
+
* Compose the prompt handed to the agent CLI: locator, fenced snippet,
|
|
81
|
+
* instruction. The scaffold is English on purpose — consumed by the agent,
|
|
82
|
+
* not shown in the UI.
|
|
96
83
|
*/
|
|
97
84
|
export function buildPrompt(context, instruction) {
|
|
98
85
|
return commentParts(context, instruction, `In ${locatorFor(context)}:`).join('\n\n');
|
package/lib/askAgent/queue.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ import { ISignal } from '@lumino/signaling';
|
|
|
3
3
|
import type { AskAgentTarget, IAskAgentContext } from './tokens';
|
|
4
4
|
/**
|
|
5
5
|
* One queued prompt: a code selection, the user's instruction about it, and
|
|
6
|
-
* where it should go. Every prompt is independent — a queue
|
|
7
|
-
*
|
|
6
|
+
* where it should go. Every prompt is independent — a queue mixes targets
|
|
7
|
+
* freely.
|
|
8
8
|
*/
|
|
9
9
|
export interface IQueuedPrompt {
|
|
10
10
|
/**
|
|
@@ -20,22 +20,15 @@ export interface IQueuedPrompt {
|
|
|
20
20
|
*/
|
|
21
21
|
instruction: string;
|
|
22
22
|
/**
|
|
23
|
-
* The destination picked
|
|
24
|
-
*
|
|
25
|
-
* longer parses — the panel then asks for a new pick before sending.
|
|
23
|
+
* The destination picked in the popup, editable in the panel. `null` when
|
|
24
|
+
* a persisted target no longer parses — the panel then asks for a new pick.
|
|
26
25
|
*/
|
|
27
26
|
target: AskAgentTarget | null;
|
|
28
27
|
}
|
|
29
28
|
/**
|
|
30
|
-
* The accumulated ask-agent prompts awaiting a batch send.
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* the popup appends entries here instead of sending, the side panel lists
|
|
34
|
-
* and edits them, and one batch send flushes the lot, delivering each
|
|
35
|
-
* destination's prompts as one numbered message. The queue itself is a
|
|
36
|
-
* plain in-memory model; the plugin mirrors it into the JupyterLab state
|
|
37
|
-
* database (via {@link serializeQueuedPrompts}) so a page reload does not
|
|
38
|
-
* silently drop typed comments.
|
|
29
|
+
* The accumulated ask-agent prompts awaiting a batch send. A plain
|
|
30
|
+
* in-memory model; the plugin mirrors it into the state database so a page
|
|
31
|
+
* reload does not silently drop typed comments.
|
|
39
32
|
*/
|
|
40
33
|
export declare class PromptQueue {
|
|
41
34
|
constructor(items?: IQueuedPrompt[]);
|
|
@@ -64,8 +57,7 @@ export declare class PromptQueue {
|
|
|
64
57
|
*/
|
|
65
58
|
remove(id: string): void;
|
|
66
59
|
/**
|
|
67
|
-
* Remove several queued prompts at once (one signal emission)
|
|
68
|
-
* a batch send succeeds for one target while other targets' prompts stay.
|
|
60
|
+
* Remove several queued prompts at once (one signal emission).
|
|
69
61
|
*/
|
|
70
62
|
removeMany(ids: readonly string[]): void;
|
|
71
63
|
/**
|
|
@@ -80,14 +72,12 @@ export declare class PromptQueue {
|
|
|
80
72
|
private _changed;
|
|
81
73
|
}
|
|
82
74
|
/**
|
|
83
|
-
* Rebuild queued prompts from
|
|
84
|
-
*
|
|
85
|
-
* convenience buffer, not a document.
|
|
75
|
+
* Rebuild queued prompts from the state database; entries that no longer
|
|
76
|
+
* parse are dropped silently.
|
|
86
77
|
*/
|
|
87
78
|
export declare function deserializeQueuedPrompts(value: unknown): IQueuedPrompt[];
|
|
88
79
|
/**
|
|
89
80
|
* The queue as a JSON value for the state database. Ids are session-scoped
|
|
90
|
-
*
|
|
91
|
-
* assigns fresh ones on load.
|
|
81
|
+
* and not persisted; fresh ones are assigned on load.
|
|
92
82
|
*/
|
|
93
83
|
export declare function serializeQueuedPrompts(items: readonly IQueuedPrompt[]): ReadonlyPartialJSONValue;
|
package/lib/askAgent/queue.js
CHANGED
|
@@ -4,15 +4,9 @@ function nextId() {
|
|
|
4
4
|
return `queued-${Date.now().toString(36)}-${idCounter++}`;
|
|
5
5
|
}
|
|
6
6
|
/**
|
|
7
|
-
* The accumulated ask-agent prompts awaiting a batch send.
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* the popup appends entries here instead of sending, the side panel lists
|
|
11
|
-
* and edits them, and one batch send flushes the lot, delivering each
|
|
12
|
-
* destination's prompts as one numbered message. The queue itself is a
|
|
13
|
-
* plain in-memory model; the plugin mirrors it into the JupyterLab state
|
|
14
|
-
* database (via {@link serializeQueuedPrompts}) so a page reload does not
|
|
15
|
-
* silently drop typed comments.
|
|
7
|
+
* The accumulated ask-agent prompts awaiting a batch send. A plain
|
|
8
|
+
* in-memory model; the plugin mirrors it into the state database so a page
|
|
9
|
+
* reload does not silently drop typed comments.
|
|
16
10
|
*/
|
|
17
11
|
export class PromptQueue {
|
|
18
12
|
constructor(items = []) {
|
|
@@ -80,8 +74,7 @@ export class PromptQueue {
|
|
|
80
74
|
this.removeMany([id]);
|
|
81
75
|
}
|
|
82
76
|
/**
|
|
83
|
-
* Remove several queued prompts at once (one signal emission)
|
|
84
|
-
* a batch send succeeds for one target while other targets' prompts stay.
|
|
77
|
+
* Remove several queued prompts at once (one signal emission).
|
|
85
78
|
*/
|
|
86
79
|
removeMany(ids) {
|
|
87
80
|
const drop = new Set(ids);
|
|
@@ -109,9 +102,8 @@ export class PromptQueue {
|
|
|
109
102
|
}
|
|
110
103
|
}
|
|
111
104
|
/**
|
|
112
|
-
* Validate one persisted context
|
|
113
|
-
*
|
|
114
|
-
* state-database edits) degrades an entry instead of poisoning the queue.
|
|
105
|
+
* Validate one persisted context; schema drift degrades an entry instead
|
|
106
|
+
* of poisoning the queue.
|
|
115
107
|
*/
|
|
116
108
|
function sanitizeContext(value) {
|
|
117
109
|
if (value === null || typeof value !== 'object') {
|
|
@@ -170,9 +162,8 @@ function sanitizeTarget(value) {
|
|
|
170
162
|
return null;
|
|
171
163
|
}
|
|
172
164
|
/**
|
|
173
|
-
* Rebuild queued prompts from
|
|
174
|
-
*
|
|
175
|
-
* convenience buffer, not a document.
|
|
165
|
+
* Rebuild queued prompts from the state database; entries that no longer
|
|
166
|
+
* parse are dropped silently.
|
|
176
167
|
*/
|
|
177
168
|
export function deserializeQueuedPrompts(value) {
|
|
178
169
|
if (!Array.isArray(value)) {
|
|
@@ -195,8 +186,7 @@ export function deserializeQueuedPrompts(value) {
|
|
|
195
186
|
}
|
|
196
187
|
/**
|
|
197
188
|
* The queue as a JSON value for the state database. Ids are session-scoped
|
|
198
|
-
*
|
|
199
|
-
* assigns fresh ones on load.
|
|
189
|
+
* and not persisted; fresh ones are assigned on load.
|
|
200
190
|
*/
|
|
201
191
|
export function serializeQueuedPrompts(items) {
|
|
202
192
|
return items.map(({ context, instruction, target }) => ({
|
|
@@ -6,24 +6,20 @@ import type { IAgent } from '../launcher/agents';
|
|
|
6
6
|
import type { PromptQueue } from './queue';
|
|
7
7
|
import type { ISessionTarget } from './targetPicker';
|
|
8
8
|
/**
|
|
9
|
-
* The right-sidebar review panel for queued ask-agent prompts
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* send button that flushes the whole queue in one go: prompts sharing a
|
|
14
|
-
* destination are combined into one numbered message, and each destination
|
|
15
|
-
* gets its own delivery. The widget re-renders on queue changes itself; the
|
|
16
|
-
* plugin additionally ties it to the agent registry and terminal signals so
|
|
17
|
-
* the destination choices stay current.
|
|
9
|
+
* The right-sidebar review panel for queued ask-agent prompts: an editable
|
|
10
|
+
* list with per-prompt destinations, plus a send button that flushes the
|
|
11
|
+
* whole queue, combining prompts that share a destination into one
|
|
12
|
+
* numbered message.
|
|
18
13
|
*/
|
|
19
14
|
export declare class AskAgentQueuePanel extends ReactWidget {
|
|
20
15
|
constructor(options: AskAgentQueuePanel.IOptions);
|
|
16
|
+
/**
|
|
17
|
+
* Render the panel content.
|
|
18
|
+
*/
|
|
21
19
|
render(): JSX.Element;
|
|
22
20
|
/**
|
|
23
|
-
* Dispose on close
|
|
24
|
-
*
|
|
25
|
-
* behind. The plugin recreates the panel in the side area on demand; the
|
|
26
|
-
* queue itself lives on in the model.
|
|
21
|
+
* Dispose on close rather than leaving a detached widget behind; the
|
|
22
|
+
* plugin recreates the panel on demand and the queue lives on in the model.
|
|
27
23
|
*/
|
|
28
24
|
protected onCloseRequest(msg: Message): void;
|
|
29
25
|
private _onQueueChanged;
|
|
@@ -54,9 +50,8 @@ export declare namespace AskAgentQueuePanel {
|
|
|
54
50
|
*/
|
|
55
51
|
targets: () => ISessionTarget[];
|
|
56
52
|
/**
|
|
57
|
-
* Live reader of whether a batch send is in flight
|
|
58
|
-
*
|
|
59
|
-
* flush cannot be double-delivered.
|
|
53
|
+
* Live reader of whether a batch send is in flight; while true the send
|
|
54
|
+
* and clear buttons are disabled.
|
|
60
55
|
*/
|
|
61
56
|
sending: () => boolean;
|
|
62
57
|
/**
|
|
@@ -64,8 +59,8 @@ export declare namespace AskAgentQueuePanel {
|
|
|
64
59
|
*/
|
|
65
60
|
trans: TranslationBundle;
|
|
66
61
|
/**
|
|
67
|
-
* Send every queued prompt to its own destination (
|
|
68
|
-
*
|
|
62
|
+
* Send every queued prompt to its own destination (called only while
|
|
63
|
+
* all instructions and destinations are valid).
|
|
69
64
|
*/
|
|
70
65
|
onSend: () => void;
|
|
71
66
|
/**
|
|
@@ -4,23 +4,14 @@ import { closeIcon, HTMLSelect, ReactWidget } from '@jupyterlab/ui-components';
|
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import { contextSummary } from './popup';
|
|
6
6
|
import { serverPath } from './prompt';
|
|
7
|
-
/**
|
|
8
|
-
* Command the context buttons dispatch; keeps the panel decoupled from the plugin.
|
|
9
|
-
*/
|
|
10
7
|
const HIGHLIGHT_LINES_COMMAND = 'xtralab:highlight-lines';
|
|
11
8
|
/**
|
|
12
|
-
* Textarea height that fits `text` without scrolling,
|
|
13
|
-
*
|
|
14
|
-
* crowd out the rest of the queue.
|
|
9
|
+
* Textarea height that fits `text` without scrolling, bounded so one long
|
|
10
|
+
* comment cannot crowd out the rest of the queue.
|
|
15
11
|
*/
|
|
16
12
|
function rowsFor(text) {
|
|
17
13
|
return Math.min(8, Math.max(2, text.split('\n').length));
|
|
18
14
|
}
|
|
19
|
-
/**
|
|
20
|
-
* A target as a `<select>` option value: `session:<name>` for a running
|
|
21
|
-
* agent terminal, `new:<agentId>` for a fresh terminal, `''` for a missing
|
|
22
|
-
* target (the placeholder option).
|
|
23
|
-
*/
|
|
24
15
|
function encodeTarget(target) {
|
|
25
16
|
if (target === null) {
|
|
26
17
|
return '';
|
|
@@ -38,10 +29,6 @@ function decodeTarget(value) {
|
|
|
38
29
|
}
|
|
39
30
|
return null;
|
|
40
31
|
}
|
|
41
|
-
/**
|
|
42
|
-
* Whether `target` can be sent to right now: its session is still running,
|
|
43
|
-
* or its agent still accepts a command-line prompt.
|
|
44
|
-
*/
|
|
45
32
|
function targetIsLive(target, agents, targets) {
|
|
46
33
|
if (target === null) {
|
|
47
34
|
return false;
|
|
@@ -52,8 +39,8 @@ function targetIsLive(target, agents, targets) {
|
|
|
52
39
|
}
|
|
53
40
|
function QueuePanelComponent(props) {
|
|
54
41
|
const { queue, commands, agents: readAgents, targets: readTargets, sending: readSending, trans, onSend, onClear } = props;
|
|
55
|
-
//
|
|
56
|
-
//
|
|
42
|
+
// The widget re-renders on every queue, agent registry and terminal
|
|
43
|
+
// change, so these snapshots stay current.
|
|
57
44
|
const items = queue.items;
|
|
58
45
|
const agents = readAgents();
|
|
59
46
|
const targets = readTargets();
|
|
@@ -65,10 +52,8 @@ function QueuePanelComponent(props) {
|
|
|
65
52
|
var _a;
|
|
66
53
|
const { context } = item;
|
|
67
54
|
const path = serverPath(context);
|
|
68
|
-
// The highlighter needs line numbers
|
|
69
|
-
//
|
|
70
|
-
// selections may come from another revision — just open the document
|
|
71
|
-
// in those cases.
|
|
55
|
+
// The highlighter needs working-file line numbers: notebook lines are
|
|
56
|
+
// cell-relative and diff lines may index another revision — just open.
|
|
72
57
|
const jump = context.cell === undefined &&
|
|
73
58
|
context.startLine !== undefined &&
|
|
74
59
|
context.linesInWorkingFile !== false &&
|
|
@@ -97,9 +82,6 @@ function QueuePanelComponent(props) {
|
|
|
97
82
|
const missing = item.instruction.trim().length === 0;
|
|
98
83
|
const target = item.target;
|
|
99
84
|
const live = targetIsLive(target, agents, targets);
|
|
100
|
-
// Say what sending will do for this prompt — paste into a running
|
|
101
|
-
// terminal, or start a fresh one — and badge it with the agent's
|
|
102
|
-
// icon, so a mixed queue can be scanned without opening dropdowns.
|
|
103
85
|
let icon = null;
|
|
104
86
|
let targetTitle = trans.__('The destination picked for this prompt is gone — choose another');
|
|
105
87
|
if (live && target !== null) {
|
|
@@ -152,15 +134,10 @@ function QueuePanelComponent(props) {
|
|
|
152
134
|
: trans._n('Send %1 prompt', 'Send %1 prompts', items.length))))));
|
|
153
135
|
}
|
|
154
136
|
/**
|
|
155
|
-
* The right-sidebar review panel for queued ask-agent prompts
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
* send button that flushes the whole queue in one go: prompts sharing a
|
|
160
|
-
* destination are combined into one numbered message, and each destination
|
|
161
|
-
* gets its own delivery. The widget re-renders on queue changes itself; the
|
|
162
|
-
* plugin additionally ties it to the agent registry and terminal signals so
|
|
163
|
-
* the destination choices stay current.
|
|
137
|
+
* The right-sidebar review panel for queued ask-agent prompts: an editable
|
|
138
|
+
* list with per-prompt destinations, plus a send button that flushes the
|
|
139
|
+
* whole queue, combining prompts that share a destination into one
|
|
140
|
+
* numbered message.
|
|
164
141
|
*/
|
|
165
142
|
export class AskAgentQueuePanel extends ReactWidget {
|
|
166
143
|
constructor(options) {
|
|
@@ -169,14 +146,15 @@ export class AskAgentQueuePanel extends ReactWidget {
|
|
|
169
146
|
this.addClass('jp-xtralab-AskAgentQueue');
|
|
170
147
|
options.queue.changed.connect(this._onQueueChanged, this);
|
|
171
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* Render the panel content.
|
|
151
|
+
*/
|
|
172
152
|
render() {
|
|
173
153
|
return React.createElement(QueuePanelComponent, { ...this._options });
|
|
174
154
|
}
|
|
175
155
|
/**
|
|
176
|
-
* Dispose on close
|
|
177
|
-
*
|
|
178
|
-
* behind. The plugin recreates the panel in the side area on demand; the
|
|
179
|
-
* queue itself lives on in the model.
|
|
156
|
+
* Dispose on close rather than leaving a detached widget behind; the
|
|
157
|
+
* plugin recreates the panel on demand and the queue lives on in the model.
|
|
180
158
|
*/
|
|
181
159
|
onCloseRequest(msg) {
|
|
182
160
|
super.onCloseRequest(msg);
|
|
@@ -26,18 +26,11 @@ export interface ISessionTarget {
|
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
28
|
* The chip row picking where a prompt goes: "New terminal" plus one chip
|
|
29
|
-
* per running agent session. Renders nothing while no
|
|
30
|
-
*
|
|
31
|
-
* be noise).
|
|
29
|
+
* per running agent session. Renders nothing while no session is running
|
|
30
|
+
* (a new terminal is then the only possibility).
|
|
32
31
|
*/
|
|
33
32
|
export declare function TargetChips(props: {
|
|
34
|
-
/**
|
|
35
|
-
* Agents that could start in a new terminal; gates the "New terminal" chip.
|
|
36
|
-
*/
|
|
37
33
|
agents: IAgent[];
|
|
38
|
-
/**
|
|
39
|
-
* The running agent sessions.
|
|
40
|
-
*/
|
|
41
34
|
targets: ISessionTarget[];
|
|
42
35
|
/**
|
|
43
36
|
* The selected session name, or `null` for a new terminal.
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { addIcon } from '@jupyterlab/ui-components';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
/**
|
|
4
|
-
* Keyboard support
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* radio, wrapping around. Selection follows focus, so the handler clicks
|
|
8
|
-
* the neighbour and the re-render moves the roving tabindex along.
|
|
4
|
+
* Keyboard support for the radiogroups, per the ARIA radio pattern: one tab
|
|
5
|
+
* stop, arrow keys move and select — the handler clicks the neighbour and
|
|
6
|
+
* the re-render moves the roving tabindex along.
|
|
9
7
|
*/
|
|
10
8
|
function onRadioGroupKeyDown(event) {
|
|
11
9
|
let delta;
|
|
@@ -33,9 +31,8 @@ function onRadioGroupKeyDown(event) {
|
|
|
33
31
|
}
|
|
34
32
|
/**
|
|
35
33
|
* The chip row picking where a prompt goes: "New terminal" plus one chip
|
|
36
|
-
* per running agent session. Renders nothing while no
|
|
37
|
-
*
|
|
38
|
-
* be noise).
|
|
34
|
+
* per running agent session. Renders nothing while no session is running
|
|
35
|
+
* (a new terminal is then the only possibility).
|
|
39
36
|
*/
|
|
40
37
|
export function TargetChips(props) {
|
|
41
38
|
const { agents, targets, targetName, trans, onSelect } = props;
|
|
@@ -67,8 +64,6 @@ export function AgentChoices(props) {
|
|
|
67
64
|
return null;
|
|
68
65
|
}
|
|
69
66
|
return (React.createElement("div", { className: "jp-xtralab-AskAgent-agents", role: "radiogroup", "aria-label": trans.__('Agent'), onKeyDown: onRadioGroupKeyDown }, agents.map(agent => (React.createElement("button", { key: agent.id, type: "button", role: "radio", "aria-checked": agent.id === agentId, tabIndex: agent.id === agentId ? 0 : -1, title: agent.label, "aria-label": agent.label, className: 'jp-xtralab-AskAgent-agentButton' +
|
|
70
|
-
(agent.id === agentId ? ' jp-mod-selected' : ''),
|
|
71
|
-
// Keep focus where the user is typing while picking an agent.
|
|
72
|
-
onMouseDown: event => event.preventDefault(), onClick: () => onSelect(agent.id) },
|
|
67
|
+
(agent.id === agentId ? ' jp-mod-selected' : ''), onMouseDown: event => event.preventDefault(), onClick: () => onSelect(agent.id) },
|
|
73
68
|
React.createElement(agent.icon.react, { tag: "span", className: "jp-xtralab-AskAgent-agentIcon" }))))));
|
|
74
69
|
}
|
package/lib/askAgent/tokens.d.ts
CHANGED
|
@@ -1,43 +1,38 @@
|
|
|
1
1
|
import { Token } from '@lumino/coreutils';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* other plugins can reference it without importing the plugin internals.
|
|
3
|
+
* Command id opening the ask-agent popup for the current editor selection;
|
|
4
|
+
* exposed so other plugins can reference it without the plugin internals.
|
|
6
5
|
*/
|
|
7
6
|
export declare const ASK_AGENT_COMMAND = "xtralab:ask-agent";
|
|
8
7
|
/**
|
|
9
|
-
* A code location (and optionally the selected
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* selection, diff line selection — produces consistently worded prompts.
|
|
8
|
+
* A code location (and optionally the selected text) a prompt should point
|
|
9
|
+
* an agent at; the plugin composes the fields into consistently worded
|
|
10
|
+
* prompts for every entry point.
|
|
13
11
|
*/
|
|
14
12
|
export interface IAskAgentContext {
|
|
15
13
|
/**
|
|
16
|
-
* Path of the file
|
|
17
|
-
*
|
|
18
|
-
* it directly.
|
|
14
|
+
* Path of the file, relative to {@link cwd} (or to the server root when
|
|
15
|
+
* no cwd is given).
|
|
19
16
|
*/
|
|
20
17
|
path: string;
|
|
21
18
|
/**
|
|
22
|
-
* Server-relative directory the agent's terminal starts in.
|
|
23
|
-
*
|
|
24
|
-
*
|
|
19
|
+
* Server-relative directory the agent's terminal starts in. Diff
|
|
20
|
+
* selections pass the git repository root so the agent can run git
|
|
21
|
+
* commands right away.
|
|
25
22
|
*/
|
|
26
23
|
cwd?: string;
|
|
27
24
|
/**
|
|
28
|
-
* The notebook cell the selection lives in
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* `raw`). When set, {@link startLine}/{@link endLine} count within the
|
|
32
|
-
* cell's source rather than within a file.
|
|
25
|
+
* The notebook cell the selection lives in. `index` is the 0-based
|
|
26
|
+
* nbformat position, `type` the nbformat cell type; when set,
|
|
27
|
+
* {@link startLine}/{@link endLine} count within the cell's source.
|
|
33
28
|
*/
|
|
34
29
|
cell?: {
|
|
35
30
|
index: number;
|
|
36
31
|
type: string;
|
|
37
32
|
};
|
|
38
33
|
/**
|
|
39
|
-
* First selected line, 1-indexed and inclusive. Omit when no line range
|
|
40
|
-
* known
|
|
34
|
+
* First selected line, 1-indexed and inclusive. Omit when no line range
|
|
35
|
+
* is known.
|
|
41
36
|
*/
|
|
42
37
|
startLine?: number;
|
|
43
38
|
/**
|
|
@@ -46,36 +41,30 @@ export interface IAskAgentContext {
|
|
|
46
41
|
*/
|
|
47
42
|
endLine?: number;
|
|
48
43
|
/**
|
|
49
|
-
* Whether
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* whose numbers must not be used to highlight the working file. Omitted
|
|
53
|
-
* means `true`.
|
|
44
|
+
* Whether the lines index the file's current working-tree content.
|
|
45
|
+
* `false` for diff selections taken from another revision, whose numbers
|
|
46
|
+
* must not highlight the working file. Omitted means `true`.
|
|
54
47
|
*/
|
|
55
48
|
linesInWorkingFile?: boolean;
|
|
56
49
|
/**
|
|
57
|
-
* The selected source text
|
|
58
|
-
* the prompt then relies on the path and line range alone.
|
|
50
|
+
* The selected source text; may be empty when only a location is known.
|
|
59
51
|
*/
|
|
60
52
|
text: string;
|
|
61
53
|
/**
|
|
62
|
-
* Extra agent-facing locator appended after the line range
|
|
63
|
-
*
|
|
64
|
-
* it is consumed by the agent, not shown in the UI.
|
|
54
|
+
* Extra agent-facing locator appended after the line range, e.g. `the old
|
|
55
|
+
* side (INDEX) of the git diff`. English — consumed by the agent, not the UI.
|
|
65
56
|
*/
|
|
66
57
|
location?: string;
|
|
67
58
|
/**
|
|
68
|
-
* Short user-facing tag shown in the popup header
|
|
69
|
-
*
|
|
70
|
-
* range reads naturally as the file's current content.
|
|
59
|
+
* Short user-facing tag shown in the popup header, e.g. "old version".
|
|
60
|
+
* Translated, unlike {@link location}.
|
|
71
61
|
*/
|
|
72
62
|
note?: string;
|
|
73
63
|
}
|
|
74
64
|
/**
|
|
75
65
|
* Where a submitted prompt goes: a fresh terminal started with the chosen
|
|
76
|
-
* agent's command, or an existing
|
|
77
|
-
*
|
|
78
|
-
* is busy).
|
|
66
|
+
* agent's command, or an existing session whose running agent receives the
|
|
67
|
+
* prompt in its input box (queued by the agent itself when busy).
|
|
79
68
|
*/
|
|
80
69
|
export type AskAgentTarget = {
|
|
81
70
|
kind: 'new';
|
|
@@ -94,17 +83,15 @@ export interface IAskAgentRequest {
|
|
|
94
83
|
*/
|
|
95
84
|
context: IAskAgentContext;
|
|
96
85
|
/**
|
|
97
|
-
* Viewport rectangle the popup anchors to
|
|
98
|
-
*
|
|
99
|
-
* center of the viewport.
|
|
86
|
+
* Viewport rectangle the popup anchors to; `null` positions it near the
|
|
87
|
+
* top center of the viewport.
|
|
100
88
|
*/
|
|
101
89
|
anchor: DOMRect | null;
|
|
102
90
|
}
|
|
103
91
|
/**
|
|
104
|
-
* The ask-agent popup: a
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
* running in an existing one.
|
|
92
|
+
* The ask-agent popup: a floating prompt box that sends the given code
|
|
93
|
+
* selection plus the user's instruction to a coding agent, in a fresh or
|
|
94
|
+
* running terminal.
|
|
108
95
|
*/
|
|
109
96
|
export interface IAskAgent {
|
|
110
97
|
/**
|
|
@@ -117,8 +104,7 @@ export interface IAskAgent {
|
|
|
117
104
|
close(): void;
|
|
118
105
|
}
|
|
119
106
|
/**
|
|
120
|
-
* DI token for {@link IAskAgent}
|
|
121
|
-
*
|
|
122
|
-
* by the git diff plugins to offer "ask an agent about these lines".
|
|
107
|
+
* DI token for {@link IAskAgent}; consumed optionally by the git diff
|
|
108
|
+
* plugins so diffs still render when the plugin is disabled.
|
|
123
109
|
*/
|
|
124
110
|
export declare const IAskAgent: Token<IAskAgent>;
|
package/lib/askAgent/tokens.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { Token } from '@lumino/coreutils';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* other plugins can reference it without importing the plugin internals.
|
|
3
|
+
* Command id opening the ask-agent popup for the current editor selection;
|
|
4
|
+
* exposed so other plugins can reference it without the plugin internals.
|
|
6
5
|
*/
|
|
7
6
|
export const ASK_AGENT_COMMAND = 'xtralab:ask-agent';
|
|
8
7
|
/**
|
|
9
|
-
* DI token for {@link IAskAgent}
|
|
10
|
-
*
|
|
11
|
-
* by the git diff plugins to offer "ask an agent about these lines".
|
|
8
|
+
* DI token for {@link IAskAgent}; consumed optionally by the git diff
|
|
9
|
+
* plugins so diffs still render when the plugin is disabled.
|
|
12
10
|
*/
|
|
13
11
|
export const IAskAgent = new Token('xtralab:IAskAgent', 'A floating prompt box that sends the current code selection to a coding agent running in a terminal.');
|
|
@@ -1,18 +1,9 @@
|
|
|
1
1
|
import { JupyterFrontEndPlugin } from '@jupyterlab/application';
|
|
2
2
|
/**
|
|
3
|
-
* Contribute a search-bar-styled
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* The pill is a regular settings-driven toolbar item: this plugin registers a
|
|
8
|
-
* widget factory for it on the `IToolbarWidgetRegistry` and declares its rank
|
|
9
|
-
* in schema/command-bar.json, so users can move or disable it from the Top
|
|
10
|
-
* Bar settings like any other toolbar item.
|
|
11
|
-
*
|
|
12
|
-
* The factory is only registered when the omnibox is available — the
|
|
13
|
-
* `IOmnibox` token is provided by `xtralab:omnibox` — so the pill never
|
|
14
|
-
* appears with nothing to open (without a factory, the toolbar item resolves
|
|
15
|
-
* to an empty command button that renders nothing).
|
|
3
|
+
* Contribute a search-bar-styled pill to the top bar toolbar that opens the
|
|
4
|
+
* omnibox. It is a settings-driven toolbar item (factory here, rank in
|
|
5
|
+
* schema/command-bar.json) registered only when `IOmnibox` is provided —
|
|
6
|
+
* without a factory the item resolves to an empty button that renders nothing.
|
|
16
7
|
*/
|
|
17
8
|
declare const plugin: JupyterFrontEndPlugin<void>;
|
|
18
9
|
export default plugin;
|