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/index.js
CHANGED
|
@@ -16,87 +16,31 @@ import { deserializeQueuedPrompts, PromptQueue, serializeQueuedPrompts } from '.
|
|
|
16
16
|
import { AskAgentQueuePanel } from './queuePanel';
|
|
17
17
|
import { ASK_AGENT_COMMAND, IAskAgent } from './tokens';
|
|
18
18
|
const PLUGIN_ID = 'xtralab:ask-agent';
|
|
19
|
-
/**
|
|
20
|
-
* Command id that reveals the queued-prompts panel.
|
|
21
|
-
*/
|
|
22
19
|
const QUEUE_PANEL_COMMAND = 'xtralab:ask-agent-queue';
|
|
23
|
-
/**
|
|
24
|
-
* Widget id of the queued-prompts side panel.
|
|
25
|
-
*/
|
|
26
20
|
const QUEUE_PANEL_ID = 'xtralab-ask-agent-queue';
|
|
27
|
-
/**
|
|
28
|
-
* State-database key remembering the last agent picked in the popup.
|
|
29
|
-
*/
|
|
30
21
|
const LAST_AGENT_STATE_KEY = 'xtralab:ask-agent:agent';
|
|
31
|
-
/**
|
|
32
|
-
* State-database key remembering the last target picked in the popup.
|
|
33
|
-
*/
|
|
34
22
|
const LAST_TARGET_STATE_KEY = 'xtralab:ask-agent:target';
|
|
35
|
-
/**
|
|
36
|
-
* State-database key holding the queued prompts across page loads.
|
|
37
|
-
*/
|
|
38
23
|
const QUEUE_STATE_KEY = 'xtralab:ask-agent:queue';
|
|
39
|
-
/**
|
|
40
|
-
* Debounce for mirroring the queue into the state database, so typing in
|
|
41
|
-
* the panel's textareas does not issue a write per keystroke.
|
|
42
|
-
*/
|
|
43
24
|
const QUEUE_PERSIST_MS = 500;
|
|
44
|
-
/**
|
|
45
|
-
* Stored target value for "start the agent in a new terminal".
|
|
46
|
-
*/
|
|
47
25
|
const NEW_TARGET_VALUE = 'new';
|
|
48
|
-
/**
|
|
49
|
-
* Stored-target prefix for an existing session; the session name follows.
|
|
50
|
-
*/
|
|
51
26
|
const SESSION_TARGET_PREFIX = 'session:';
|
|
52
27
|
/**
|
|
53
|
-
* Delay
|
|
54
|
-
* appears once the selection settles rather than flickering along a drag.
|
|
28
|
+
* Delay before showing the pill, so it does not flicker along a drag.
|
|
55
29
|
*/
|
|
56
30
|
const SELECTION_SETTLE_MS = 250;
|
|
57
31
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* sees it; `Accel .` — the "quick fix" chord elsewhere — is free in the
|
|
62
|
-
* editor, the browser and JupyterLab.
|
|
32
|
+
* `Accel I` would be the familiar "inline chat" chord but CodeMirror's
|
|
33
|
+
* default keymap owns `Mod-i` and prevents-default before Lumino sees it;
|
|
34
|
+
* `Accel .` is free in the editor, the browser and JupyterLab.
|
|
63
35
|
*/
|
|
64
36
|
const ASK_AGENT_KEYS = 'Accel .';
|
|
65
|
-
/**
|
|
66
|
-
* Gap between the pill and the selection anchor, in pixels.
|
|
67
|
-
*/
|
|
68
37
|
const PILL_GAP = 6;
|
|
69
|
-
/**
|
|
70
|
-
* Minimum distance kept between the pill and the viewport edges.
|
|
71
|
-
*/
|
|
72
38
|
const PILL_VIEWPORT_MARGIN = 8;
|
|
73
39
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* CodeMirror file editor or notebook cell grows a small floating "Ask agent"
|
|
79
|
-
* pill next to the selection. Clicking it (or running `xtralab:ask-agent`,
|
|
80
|
-
* bound to Accel+. in editors and notebooks) opens a popup where the user
|
|
81
|
-
* types an instruction, picks one of the launcher's agents and picks where
|
|
82
|
-
* the prompt goes; submitting either starts that agent in a fresh terminal
|
|
83
|
-
* via `xtralab:start-agent:<id>`, or pastes the prompt into an agent already
|
|
84
|
-
* running in one of the open terminal sessions (via `IAgentTerminals`; the
|
|
85
|
-
* agent CLIs queue prompts that arrive while they are busy). Sends to a
|
|
86
|
-
* running agent stay in the background — focus never leaves the editor, and
|
|
87
|
-
* a success toast offers to open the terminal. Either way the prompt embeds
|
|
88
|
-
* the file path, cell index for notebooks, line range and selected snippet.
|
|
89
|
-
*
|
|
90
|
-
* The popup's Queue button (or Accel+Enter) defers the send instead: the
|
|
91
|
-
* comment lands in a persistent queue, stamped with the popup's selected
|
|
92
|
-
* destination — every queued prompt is independent and may aim at a
|
|
93
|
-
* different agent or session. A right-sidebar panel reviews the queue
|
|
94
|
-
* (edit, retarget, remove) and flushes it in one go, combining prompts that
|
|
95
|
-
* share a destination into a single numbered message. The queue survives
|
|
96
|
-
* page reloads.
|
|
97
|
-
*
|
|
98
|
-
* The same popup is provided on the `IAskAgent` token so the git diff
|
|
99
|
-
* viewers can open it for a selected diff line range.
|
|
40
|
+
* Prompt a coding agent about selected code: a pill/popup over editor,
|
|
41
|
+
* notebook-cell and git-diff selections sends the instruction to a fresh
|
|
42
|
+
* agent terminal or into a running one, or defers it into a persistent
|
|
43
|
+
* queue reviewed in a right-sidebar panel and flushed as one batch.
|
|
100
44
|
*/
|
|
101
45
|
const plugin = {
|
|
102
46
|
id: PLUGIN_ID,
|
|
@@ -115,16 +59,15 @@ const plugin = {
|
|
|
115
59
|
activate: (app, agentRegistry, palette, translator, agentTerminals, labShell, restorer, state) => {
|
|
116
60
|
const trans = (translator !== null && translator !== void 0 ? translator : nullTranslator).load('jupyterlab');
|
|
117
61
|
/**
|
|
118
|
-
* Best-effort
|
|
119
|
-
* convenience of restoring this value on the next page load.
|
|
62
|
+
* Best-effort state-database write; a failure only loses a restored default.
|
|
120
63
|
*/
|
|
121
64
|
const saveState = (key, value) => {
|
|
122
65
|
state === null || state === void 0 ? void 0 : state.save(key, value).catch(error => {
|
|
123
66
|
console.error('xtralab: failed to persist ask-agent state', error);
|
|
124
67
|
});
|
|
125
68
|
};
|
|
126
|
-
//
|
|
127
|
-
//
|
|
69
|
+
// Last-used picks, restored asynchronously but read synchronously by
|
|
70
|
+
// the popup.
|
|
128
71
|
let lastAgentId = null;
|
|
129
72
|
let lastTarget = null;
|
|
130
73
|
if (state !== null) {
|
|
@@ -152,20 +95,14 @@ const plugin = {
|
|
|
152
95
|
lastTarget = value;
|
|
153
96
|
saveState(LAST_TARGET_STATE_KEY, value);
|
|
154
97
|
};
|
|
155
|
-
/**
|
|
156
|
-
* Agents that can receive an initial prompt on their command line.
|
|
157
|
-
*/
|
|
158
98
|
const promptAgents = () => {
|
|
159
99
|
var _a;
|
|
160
100
|
return ((_a = agentRegistry === null || agentRegistry === void 0 ? void 0 : agentRegistry.agents) !== null && _a !== void 0 ? _a : []).filter(agent => agent.promptArgs !== undefined);
|
|
161
101
|
};
|
|
162
102
|
/**
|
|
163
|
-
* Running agent terminals offered as prompt targets,
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
* back to the plain terminal icon when the agent has since been removed
|
|
167
|
-
* from the settings). Unlike {@link promptAgents} this does not require
|
|
168
|
-
* `promptArgs`: pasting into a running TUI needs no command-line recipe.
|
|
103
|
+
* Running agent terminals offered as prompt targets, badged with the
|
|
104
|
+
* matching agent's icon like the terminals panel (configured command or
|
|
105
|
+
* canonical id). Pasting into a running TUI needs no `promptArgs`.
|
|
169
106
|
*/
|
|
170
107
|
const sessionTargets = () => {
|
|
171
108
|
var _a;
|
|
@@ -194,24 +131,18 @@ const plugin = {
|
|
|
194
131
|
pill.style.display = 'none';
|
|
195
132
|
}
|
|
196
133
|
};
|
|
197
|
-
/**
|
|
198
|
-
* Open the named terminal's tab (the success toast's call to action).
|
|
199
|
-
*/
|
|
200
134
|
const openTerminal = (name) => {
|
|
201
135
|
app.commands.execute('terminal:open', { name }).catch(reason => {
|
|
202
136
|
console.error('xtralab: failed to open the terminal', reason);
|
|
203
137
|
});
|
|
204
138
|
};
|
|
205
139
|
/**
|
|
206
|
-
* Paste `prompt` into the running agent in session `name
|
|
207
|
-
* background
|
|
208
|
-
*
|
|
209
|
-
* still rejects so callers can chain their own cleanup to success only.
|
|
140
|
+
* Paste `prompt` into the running agent in session `name`, in the
|
|
141
|
+
* background. Failures are toasted but still reject, so callers can
|
|
142
|
+
* chain their own cleanup to success only.
|
|
210
143
|
*/
|
|
211
144
|
const deliverToSession = async (name, prompt, successMessage) => {
|
|
212
145
|
if (agentTerminals === null) {
|
|
213
|
-
// Session targets are only offered when the terminals plugin is
|
|
214
|
-
// present; fail loudly rather than resolving as a delivered send.
|
|
215
146
|
throw new Error('xtralab: agent terminals are unavailable');
|
|
216
147
|
}
|
|
217
148
|
try {
|
|
@@ -234,8 +165,7 @@ const plugin = {
|
|
|
234
165
|
};
|
|
235
166
|
/**
|
|
236
167
|
* Start `agentId` in a fresh terminal with `prompt` on its command
|
|
237
|
-
* line. Failures are toasted
|
|
238
|
-
* chain their own cleanup to success only.
|
|
168
|
+
* line. Failures are toasted but still reject.
|
|
239
169
|
*/
|
|
240
170
|
const startAgentTerminal = async (agentId, prompt, cwd) => {
|
|
241
171
|
const args = { prompt };
|
|
@@ -251,9 +181,8 @@ const plugin = {
|
|
|
251
181
|
throw error;
|
|
252
182
|
}
|
|
253
183
|
};
|
|
254
|
-
// The queue
|
|
255
|
-
//
|
|
256
|
-
// without the full Lab shell.
|
|
184
|
+
// The queue needs a side area for its review panel, so it stays off
|
|
185
|
+
// (and the popup hides its Queue button) without the full Lab shell.
|
|
257
186
|
let queue = null;
|
|
258
187
|
let queuePrompt = null;
|
|
259
188
|
if (labShell !== null) {
|
|
@@ -261,8 +190,8 @@ const plugin = {
|
|
|
261
190
|
queue = promptQueue;
|
|
262
191
|
let panel = null;
|
|
263
192
|
let flushing = false;
|
|
264
|
-
//
|
|
265
|
-
//
|
|
193
|
+
// Debounced so typing in the panel's textareas does not write on
|
|
194
|
+
// each keystroke.
|
|
266
195
|
const persistQueue = new Debouncer(() => {
|
|
267
196
|
saveState(QUEUE_STATE_KEY, serializeQueuedPrompts(promptQueue.items));
|
|
268
197
|
}, QUEUE_PERSIST_MS);
|
|
@@ -270,12 +199,9 @@ const plugin = {
|
|
|
270
199
|
void persistQueue.invoke();
|
|
271
200
|
});
|
|
272
201
|
/**
|
|
273
|
-
* The prompt (and
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
* starts at the server root instead, with every locator rewritten to
|
|
277
|
-
* a server-relative path so none of them depends on the terminal's
|
|
278
|
-
* cwd.
|
|
202
|
+
* The prompt (and cwd) for a batch sent to a new terminal: a shared
|
|
203
|
+
* repository root becomes the cwd; a mixed batch starts at the server
|
|
204
|
+
* root with every locator rewritten server-relative instead.
|
|
279
205
|
*/
|
|
280
206
|
const newTerminalBatch = (items) => {
|
|
281
207
|
const cwds = new Set(items.map(item => { var _a; return (_a = item.context.cwd) !== null && _a !== void 0 ? _a : ''; }));
|
|
@@ -297,13 +223,10 @@ const plugin = {
|
|
|
297
223
|
return { prompt: buildBatchPrompt(normalized) };
|
|
298
224
|
};
|
|
299
225
|
/**
|
|
300
|
-
* Flush the queue: prompts are grouped by destination
|
|
301
|
-
*
|
|
302
|
-
*
|
|
303
|
-
*
|
|
304
|
-
* session never loses the comments aimed elsewhere. One flush runs
|
|
305
|
-
* at a time — deliveries span server round trips, and a second click
|
|
306
|
-
* meanwhile would re-send every still-queued group.
|
|
226
|
+
* Flush the queue: prompts are grouped by destination and each group
|
|
227
|
+
* goes out as one numbered message, leaving the queue only when its
|
|
228
|
+
* delivery succeeds. One flush at a time — a second click mid-flight
|
|
229
|
+
* would re-send every still-queued group.
|
|
307
230
|
*/
|
|
308
231
|
const sendQueue = () => {
|
|
309
232
|
var _a, _b, _c;
|
|
@@ -313,8 +236,8 @@ const plugin = {
|
|
|
313
236
|
const groups = new Map();
|
|
314
237
|
for (const item of promptQueue.items) {
|
|
315
238
|
if (item.target === null) {
|
|
316
|
-
// The panel disables sending
|
|
317
|
-
//
|
|
239
|
+
// The panel disables sending without a target; skip if a send
|
|
240
|
+
// races a target loss.
|
|
318
241
|
continue;
|
|
319
242
|
}
|
|
320
243
|
const key = item.target.kind === 'session'
|
|
@@ -328,9 +251,8 @@ const plugin = {
|
|
|
328
251
|
for (const { target, items } of groups.values()) {
|
|
329
252
|
/**
|
|
330
253
|
* Remove the delivered prompts — except any edited or retargeted
|
|
331
|
-
*
|
|
332
|
-
*
|
|
333
|
-
* queued for the next flush instead of being dropped unsent.
|
|
254
|
+
* in flight: an edit makes a new object, so identity is the
|
|
255
|
+
* "unchanged" check and the edited prompt stays queued.
|
|
334
256
|
*/
|
|
335
257
|
const delivered = () => {
|
|
336
258
|
promptQueue.removeMany(items
|
|
@@ -359,16 +281,12 @@ const plugin = {
|
|
|
359
281
|
}
|
|
360
282
|
flushing = true;
|
|
361
283
|
panel === null || panel === void 0 ? void 0 : panel.update();
|
|
362
|
-
// Every delivery caught its own failure
|
|
363
|
-
// once all groups have settled either way.
|
|
284
|
+
// Every delivery caught its own failure, so this settles either way.
|
|
364
285
|
void Promise.all(deliveries).then(() => {
|
|
365
286
|
flushing = false;
|
|
366
287
|
panel === null || panel === void 0 ? void 0 : panel.update();
|
|
367
288
|
});
|
|
368
289
|
};
|
|
369
|
-
/**
|
|
370
|
-
* Empty the queue, with an undo toast (typed comments are work).
|
|
371
|
-
*/
|
|
372
290
|
const clearQueue = () => {
|
|
373
291
|
const removed = promptQueue.items;
|
|
374
292
|
if (removed.length === 0) {
|
|
@@ -380,8 +298,8 @@ const plugin = {
|
|
|
380
298
|
actions: [
|
|
381
299
|
{
|
|
382
300
|
label: trans.__('Undo'),
|
|
383
|
-
// Prompts queued after the clear are newer; keep them
|
|
384
|
-
//
|
|
301
|
+
// Prompts queued after the clear are newer; keep them after
|
|
302
|
+
// the restored ones.
|
|
385
303
|
callback: () => promptQueue.reset([...removed, ...promptQueue.items])
|
|
386
304
|
}
|
|
387
305
|
]
|
|
@@ -403,12 +321,9 @@ const plugin = {
|
|
|
403
321
|
created.title.icon = askAgentIcon;
|
|
404
322
|
created.title.label = trans.__('Prompt Queue');
|
|
405
323
|
created.title.caption = trans.__('Queued ask-agent prompts');
|
|
406
|
-
// Closable so it gets a close button
|
|
407
|
-
//
|
|
408
|
-
// demand (same arrangement as the walkthrough panel).
|
|
324
|
+
// Closable so it gets a close button when dragged out of the side
|
|
325
|
+
// area; closing disposes it and it is recreated on demand.
|
|
409
326
|
created.title.closable = true;
|
|
410
|
-
// The panel re-renders on queue changes itself; the chips also
|
|
411
|
-
// mirror the live agent list and terminal sessions.
|
|
412
327
|
agentRegistry === null || agentRegistry === void 0 ? void 0 : agentRegistry.changed.connect(created.update, created);
|
|
413
328
|
agentTerminals === null || agentTerminals === void 0 ? void 0 : agentTerminals.changed.connect(created.update, created);
|
|
414
329
|
labShell.add(created, 'right', { rank: 900 });
|
|
@@ -428,8 +343,6 @@ const plugin = {
|
|
|
428
343
|
queuePrompt = (request, target, instruction) => {
|
|
429
344
|
var _a;
|
|
430
345
|
const wasEmpty = promptQueue.items.length === 0;
|
|
431
|
-
// Queueing is a target choice like sending: remember it for the
|
|
432
|
-
// next popup's preselection.
|
|
433
346
|
if (target.kind === 'session') {
|
|
434
347
|
rememberTarget(SESSION_TARGET_PREFIX + target.name);
|
|
435
348
|
}
|
|
@@ -438,18 +351,14 @@ const plugin = {
|
|
|
438
351
|
rememberTarget(NEW_TARGET_VALUE);
|
|
439
352
|
}
|
|
440
353
|
promptQueue.add(request.context, instruction, target);
|
|
441
|
-
// Queueing is background like a session send: hand focus straight
|
|
442
|
-
// back to the widget the ask came from.
|
|
443
354
|
(_a = app.shell.currentWidget) === null || _a === void 0 ? void 0 : _a.activate();
|
|
444
355
|
const queuePanel = ensurePanel();
|
|
445
356
|
if (queuePanel.isVisible) {
|
|
446
|
-
// The list visibly grows; no extra feedback needed.
|
|
447
357
|
return;
|
|
448
358
|
}
|
|
449
359
|
if (wasEmpty) {
|
|
450
|
-
//
|
|
451
|
-
//
|
|
452
|
-
// a deliberately closed sidebar and toast instead.
|
|
360
|
+
// Reveal the panel once for the first prompt; later additions
|
|
361
|
+
// respect a deliberately closed sidebar and toast instead.
|
|
453
362
|
labShell.activateById(queuePanel.id);
|
|
454
363
|
return;
|
|
455
364
|
}
|
|
@@ -464,10 +373,8 @@ const plugin = {
|
|
|
464
373
|
icon: askAgentIcon,
|
|
465
374
|
execute: revealPanel
|
|
466
375
|
});
|
|
467
|
-
//
|
|
468
|
-
//
|
|
469
|
-
// restored prompts. A restored queue should be discoverable without
|
|
470
|
-
// queueing anything new, so its sidebar tab is recreated (collapsed).
|
|
376
|
+
// Prompts queued before the fetch resolves are newer and stay, after
|
|
377
|
+
// the restored ones; the tab is recreated so the restore is discoverable.
|
|
471
378
|
if (state !== null) {
|
|
472
379
|
void state
|
|
473
380
|
.fetch(QUEUE_STATE_KEY)
|
|
@@ -488,11 +395,8 @@ const plugin = {
|
|
|
488
395
|
closePopup();
|
|
489
396
|
const agents = promptAgents();
|
|
490
397
|
const targets = sessionTargets();
|
|
491
|
-
// Preselect
|
|
492
|
-
//
|
|
493
|
-
// last-used one when it is still running, otherwise the first — unless
|
|
494
|
-
// the user explicitly chose a new terminal last time (and one can
|
|
495
|
-
// still be started).
|
|
398
|
+
// Preselect: a live session wins (last-used if still running, else the
|
|
399
|
+
// first) unless a new terminal was last chosen and can still start.
|
|
496
400
|
const storedTarget = lastTarget;
|
|
497
401
|
let initialTargetName = targets.length > 0 ? targets[0].name : null;
|
|
498
402
|
if (storedTarget === NEW_TARGET_VALUE && agents.length > 0) {
|
|
@@ -534,9 +438,8 @@ const plugin = {
|
|
|
534
438
|
const prompt = buildPrompt(request.context, instruction);
|
|
535
439
|
if (target.kind === 'session') {
|
|
536
440
|
rememberTarget(SESSION_TARGET_PREFIX + target.name);
|
|
537
|
-
// The send is background
|
|
538
|
-
//
|
|
539
|
-
// disposing the popup alone would drop it on `document.body`.
|
|
441
|
+
// The send is background: hand focus back to the widget the ask
|
|
442
|
+
// came from — disposing the popup alone drops it on `document.body`.
|
|
540
443
|
(_a = app.shell.currentWidget) === null || _a === void 0 ? void 0 : _a.activate();
|
|
541
444
|
const label = (_c = (_b = targets.find(entry => entry.name === target.name)) === null || _b === void 0 ? void 0 : _b.label) !== null && _c !== void 0 ? _c : target.name;
|
|
542
445
|
deliverToSession(target.name, prompt, trans.__('Prompt sent to %1', label)).catch(() => {
|
|
@@ -595,9 +498,8 @@ const plugin = {
|
|
|
595
498
|
const button = ensurePill();
|
|
596
499
|
pillRequest = request;
|
|
597
500
|
button.style.display = 'flex';
|
|
598
|
-
// Measure after display so the rect is real
|
|
599
|
-
//
|
|
600
|
-
// viewport).
|
|
501
|
+
// Measure after display so the rect is real; the pill sits above the
|
|
502
|
+
// selection head, below it when that would leave the viewport.
|
|
601
503
|
const rect = button.getBoundingClientRect();
|
|
602
504
|
let left = anchor.left;
|
|
603
505
|
let top = anchor.top - rect.height - PILL_GAP;
|
|
@@ -625,9 +527,6 @@ const plugin = {
|
|
|
625
527
|
hidePill();
|
|
626
528
|
return;
|
|
627
529
|
}
|
|
628
|
-
// The popup can send somewhere as long as an agent takes a prompt on
|
|
629
|
-
// its command line (new terminal) or one is already running (existing
|
|
630
|
-
// session) — only with neither is there nothing to offer.
|
|
631
530
|
if (promptAgents().length === 0 &&
|
|
632
531
|
((_a = agentTerminals === null || agentTerminals === void 0 ? void 0 : agentTerminals.sessions()) !== null && _a !== void 0 ? _a : []).length === 0) {
|
|
633
532
|
hidePill();
|
|
@@ -640,9 +539,8 @@ const plugin = {
|
|
|
640
539
|
}
|
|
641
540
|
showPill(request);
|
|
642
541
|
};
|
|
643
|
-
//
|
|
644
|
-
//
|
|
645
|
-
// pointerup listener invokes it again once the drag ends.
|
|
542
|
+
// Mid-drag the selection is still moving; the pointerup listener
|
|
543
|
+
// re-invokes once the drag ends.
|
|
646
544
|
const settled = new Debouncer(() => {
|
|
647
545
|
if (!pointerIsDown) {
|
|
648
546
|
evaluateSelection();
|
|
@@ -650,8 +548,8 @@ const plugin = {
|
|
|
650
548
|
}, SELECTION_SETTLE_MS);
|
|
651
549
|
document.addEventListener('selectionchange', () => {
|
|
652
550
|
if (popup !== null) {
|
|
653
|
-
// Typing in the popup
|
|
654
|
-
//
|
|
551
|
+
// Typing in the popup moves the document selection; the pill must
|
|
552
|
+
// not resurface underneath it.
|
|
655
553
|
return;
|
|
656
554
|
}
|
|
657
555
|
hidePill();
|
|
@@ -682,9 +580,8 @@ const plugin = {
|
|
|
682
580
|
return;
|
|
683
581
|
}
|
|
684
582
|
if (popup !== null) {
|
|
685
|
-
//
|
|
686
|
-
//
|
|
687
|
-
// the widget the ask came from.
|
|
583
|
+
// The popup's own handler consumes Escape while focus is inside it;
|
|
584
|
+
// here focus is elsewhere, so close and restore focus.
|
|
688
585
|
closePopup();
|
|
689
586
|
(_a = app.shell.currentWidget) === null || _a === void 0 ? void 0 : _a.activate();
|
|
690
587
|
return;
|
|
@@ -705,7 +602,6 @@ const plugin = {
|
|
|
705
602
|
open(request);
|
|
706
603
|
}
|
|
707
604
|
});
|
|
708
|
-
// One binding per editing surface: file editors and notebooks.
|
|
709
605
|
for (const selector of ['.jp-FileEditor', '.jp-Notebook']) {
|
|
710
606
|
app.commands.addKeyBinding({
|
|
711
607
|
command: ASK_AGENT_COMMAND,
|
package/lib/askAgent/popup.d.ts
CHANGED
|
@@ -4,20 +4,19 @@ import type { IAgent } from '../launcher/agents';
|
|
|
4
4
|
import { ISessionTarget } from './targetPicker';
|
|
5
5
|
import type { AskAgentTarget, IAskAgentContext } from './tokens';
|
|
6
6
|
/**
|
|
7
|
-
* Short
|
|
8
|
-
*
|
|
9
|
-
* line range and, for ranges that are not current file content (such as the
|
|
10
|
-
* old side of a diff), a clarifying tag.
|
|
7
|
+
* Short descriptor of the prompted range for the popup header and the queue
|
|
8
|
+
* panel: file name, notebook cell, line range and any clarifying tag.
|
|
11
9
|
*/
|
|
12
10
|
export declare function contextSummary(context: IAskAgentContext, trans: TranslationBundle): string;
|
|
13
11
|
/**
|
|
14
|
-
* The floating ask-agent prompt box
|
|
15
|
-
*
|
|
16
|
-
* JupyterLab's theme variables resolve outside the shell (the omnibox uses
|
|
17
|
-
* the same arrangement).
|
|
12
|
+
* The floating ask-agent prompt box, attached to `document.body`;
|
|
13
|
+
* `jp-ThemedContainer` makes theme variables resolve outside the shell.
|
|
18
14
|
*/
|
|
19
15
|
export declare class AskAgentPopup extends ReactWidget {
|
|
20
16
|
constructor(options: AskAgentPopup.IOptions);
|
|
17
|
+
/**
|
|
18
|
+
* Render the popup content.
|
|
19
|
+
*/
|
|
21
20
|
render(): JSX.Element;
|
|
22
21
|
private _options;
|
|
23
22
|
}
|
|
@@ -55,8 +54,7 @@ export declare namespace AskAgentPopup {
|
|
|
55
54
|
*/
|
|
56
55
|
initialTargetName: string | null;
|
|
57
56
|
/**
|
|
58
|
-
* Number of prompts already queued, shown on the queue button.
|
|
59
|
-
* meaningful together with {@link onQueue}.
|
|
57
|
+
* Number of prompts already queued, shown on the queue button.
|
|
60
58
|
*/
|
|
61
59
|
queueCount?: number;
|
|
62
60
|
/**
|
|
@@ -68,15 +66,13 @@ export declare namespace AskAgentPopup {
|
|
|
68
66
|
*/
|
|
69
67
|
onSubmit: (target: AskAgentTarget, instruction: string) => void;
|
|
70
68
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* button is hidden when omitted.
|
|
69
|
+
* Queue the instruction for the chosen target instead of sending it.
|
|
70
|
+
* The queue button is hidden when omitted.
|
|
74
71
|
*/
|
|
75
72
|
onQueue?: (target: AskAgentTarget, instruction: string) => void;
|
|
76
73
|
/**
|
|
77
|
-
* Dismiss the popup
|
|
78
|
-
*
|
|
79
|
-
* the plugin to hand focus back to the widget the ask came from.
|
|
74
|
+
* Dismiss the popup. `restoreFocus` is true when the dismissal placed
|
|
75
|
+
* no focus of its own (Escape).
|
|
80
76
|
*/
|
|
81
77
|
onCancel: (restoreFocus: boolean) => void;
|
|
82
78
|
}
|
package/lib/askAgent/popup.js
CHANGED
|
@@ -3,19 +3,11 @@ import { ReactWidget } from '@jupyterlab/ui-components';
|
|
|
3
3
|
import { CommandRegistry } from '@lumino/commands';
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import { AgentChoices, TargetChips } from './targetPicker';
|
|
6
|
-
/**
|
|
7
|
-
* Gap between the popup and its anchor rectangle, in pixels.
|
|
8
|
-
*/
|
|
9
6
|
const ANCHOR_GAP = 6;
|
|
10
|
-
/**
|
|
11
|
-
* Minimum distance kept between the popup and the viewport edges.
|
|
12
|
-
*/
|
|
13
7
|
const VIEWPORT_MARGIN = 8;
|
|
14
8
|
/**
|
|
15
|
-
* Short
|
|
16
|
-
*
|
|
17
|
-
* line range and, for ranges that are not current file content (such as the
|
|
18
|
-
* old side of a diff), a clarifying tag.
|
|
9
|
+
* Short descriptor of the prompted range for the popup header and the queue
|
|
10
|
+
* panel: file name, notebook cell, line range and any clarifying tag.
|
|
19
11
|
*/
|
|
20
12
|
export function contextSummary(context, trans) {
|
|
21
13
|
var _a;
|
|
@@ -43,14 +35,12 @@ function AskAgentPopupComponent(props) {
|
|
|
43
35
|
const known = agents.find(agent => agent.id === initialAgentId);
|
|
44
36
|
return (_b = (_a = (known !== null && known !== void 0 ? known : agents[0])) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : '';
|
|
45
37
|
});
|
|
46
|
-
// The running session the prompt goes to, or `null` for a new terminal.
|
|
47
38
|
const [targetName, setTargetName] = React.useState(initialTargetName);
|
|
48
39
|
const [position, setPosition] = React.useState(null);
|
|
49
40
|
const popupRef = React.useRef(null);
|
|
50
41
|
const textareaRef = React.useRef(null);
|
|
51
|
-
// Place the popup once its size is known
|
|
52
|
-
//
|
|
53
|
-
// the measurement never flashes at the wrong position.
|
|
42
|
+
// Place the popup once its size is known; hidden until placed so the
|
|
43
|
+
// measurement never flashes at the wrong position.
|
|
54
44
|
React.useLayoutEffect(() => {
|
|
55
45
|
const node = popupRef.current;
|
|
56
46
|
if (node === null) {
|
|
@@ -76,10 +66,8 @@ function AskAgentPopupComponent(props) {
|
|
|
76
66
|
top = Math.max(VIEWPORT_MARGIN, Math.min(top, viewportHeight - rect.height - VIEWPORT_MARGIN));
|
|
77
67
|
setPosition({ left, top });
|
|
78
68
|
}, [anchor]);
|
|
79
|
-
//
|
|
80
|
-
//
|
|
81
|
-
// refuse focus. The empty state renders no textarea; focus the dialog
|
|
82
|
-
// root itself so it is announced and Escape works without a pointer.
|
|
69
|
+
// Unpositioned means `visibility: hidden`, and hidden elements refuse focus.
|
|
70
|
+
// With no textarea (empty state) the dialog root takes focus for Escape.
|
|
83
71
|
React.useEffect(() => {
|
|
84
72
|
var _a, _b;
|
|
85
73
|
if (position !== null) {
|
|
@@ -87,14 +75,12 @@ function AskAgentPopupComponent(props) {
|
|
|
87
75
|
}
|
|
88
76
|
}, [position]);
|
|
89
77
|
const dismiss = React.useCallback((restoreFocus) => {
|
|
90
|
-
// Defer so
|
|
91
|
-
//
|
|
92
|
-
// omnibox).
|
|
78
|
+
// Defer so this React root never unmounts synchronously inside its
|
|
79
|
+
// own event handler (same pattern as the omnibox).
|
|
93
80
|
window.setTimeout(() => onCancel(restoreFocus), 0);
|
|
94
81
|
}, [onCancel]);
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
// places focus itself, so none is restored.
|
|
82
|
+
// Capture phase so a click into event-swallowing widgets still dismisses;
|
|
83
|
+
// the click places focus itself, so none is restored.
|
|
98
84
|
React.useEffect(() => {
|
|
99
85
|
const onPointerDown = (event) => {
|
|
100
86
|
const node = popupRef.current;
|
|
@@ -113,8 +99,6 @@ function AskAgentPopupComponent(props) {
|
|
|
113
99
|
const selectedSession = targets.find(target => target.name === targetName);
|
|
114
100
|
const canSubmit = instruction.trim().length > 0 &&
|
|
115
101
|
(selectedSession !== undefined || selectedAgent !== undefined);
|
|
116
|
-
// The destination both actions use: send delivers to it now, queue stamps
|
|
117
|
-
// it on the queued prompt (still editable in the panel later).
|
|
118
102
|
const resolveTarget = React.useCallback(() => {
|
|
119
103
|
const session = targets.find(entry => entry.name === targetName);
|
|
120
104
|
if (session !== undefined) {
|
|
@@ -132,8 +116,7 @@ function AskAgentPopupComponent(props) {
|
|
|
132
116
|
if (trimmed.length === 0 || target === null) {
|
|
133
117
|
return;
|
|
134
118
|
}
|
|
135
|
-
//
|
|
136
|
-
// inside the event handler that triggered it.
|
|
119
|
+
// Same deferred pattern as dismiss.
|
|
137
120
|
window.setTimeout(() => {
|
|
138
121
|
onSubmit(target, trimmed);
|
|
139
122
|
}, 0);
|
|
@@ -153,8 +136,6 @@ function AskAgentPopupComponent(props) {
|
|
|
153
136
|
if (event.key === 'Escape') {
|
|
154
137
|
event.preventDefault();
|
|
155
138
|
event.stopPropagation();
|
|
156
|
-
// A keyboard dismissal places no focus of its own; ask the plugin to
|
|
157
|
-
// hand it back to the widget the ask came from.
|
|
158
139
|
dismiss(true);
|
|
159
140
|
}
|
|
160
141
|
};
|
|
@@ -177,9 +158,8 @@ function AskAgentPopupComponent(props) {
|
|
|
177
158
|
const summary = contextSummary(context, trans);
|
|
178
159
|
const placeholder = trans.__('Describe the change…');
|
|
179
160
|
return (React.createElement("div", { ref: popupRef, className: "jp-xtralab-AskAgent-popup", role: "dialog", "aria-label": trans.__('Ask an agent about %1', summary),
|
|
180
|
-
// Focusable so clicks on non-interactive
|
|
181
|
-
//
|
|
182
|
-
// can be focused at all.
|
|
161
|
+
// Focusable so clicks on non-interactive content keep Escape working
|
|
162
|
+
// and the empty state can take focus at all.
|
|
183
163
|
tabIndex: -1, style: {
|
|
184
164
|
left: (_a = position === null || position === void 0 ? void 0 : position.left) !== null && _a !== void 0 ? _a : 0,
|
|
185
165
|
top: (_b = position === null || position === void 0 ? void 0 : position.top) !== null && _b !== void 0 ? _b : 0,
|
|
@@ -202,10 +182,8 @@ function AskAgentPopupComponent(props) {
|
|
|
202
182
|
: trans.__('Ask agent'))))))));
|
|
203
183
|
}
|
|
204
184
|
/**
|
|
205
|
-
* The floating ask-agent prompt box
|
|
206
|
-
*
|
|
207
|
-
* JupyterLab's theme variables resolve outside the shell (the omnibox uses
|
|
208
|
-
* the same arrangement).
|
|
185
|
+
* The floating ask-agent prompt box, attached to `document.body`;
|
|
186
|
+
* `jp-ThemedContainer` makes theme variables resolve outside the shell.
|
|
209
187
|
*/
|
|
210
188
|
export class AskAgentPopup extends ReactWidget {
|
|
211
189
|
constructor(options) {
|
|
@@ -215,6 +193,9 @@ export class AskAgentPopup extends ReactWidget {
|
|
|
215
193
|
this.addClass('jp-xtralab-AskAgent');
|
|
216
194
|
this.addClass('jp-ThemedContainer');
|
|
217
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* Render the popup content.
|
|
198
|
+
*/
|
|
218
199
|
render() {
|
|
219
200
|
return React.createElement(AskAgentPopupComponent, { ...this._options });
|
|
220
201
|
}
|
package/lib/askAgent/prompt.d.ts
CHANGED
|
@@ -6,11 +6,9 @@ import type { IAskAgentContext } from './tokens';
|
|
|
6
6
|
*/
|
|
7
7
|
export declare function serverPath(context: IAskAgentContext): string;
|
|
8
8
|
/**
|
|
9
|
-
* Compose the prompt handed to the agent CLI:
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* The scaffold is written in English on purpose — it is consumed by the
|
|
13
|
-
* agent, not shown in the UI, and the agent CLIs are English-first.
|
|
9
|
+
* Compose the prompt handed to the agent CLI: locator, fenced snippet,
|
|
10
|
+
* instruction. The scaffold is English on purpose — consumed by the agent,
|
|
11
|
+
* not shown in the UI.
|
|
14
12
|
*/
|
|
15
13
|
export declare function buildPrompt(context: IAskAgentContext, instruction: string): string;
|
|
16
14
|
/**
|