xtralab 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -229
- package/lib/agentSessions.d.ts +6 -2
- package/lib/askAgent/editorSelection.d.ts +53 -0
- package/lib/askAgent/editorSelection.js +95 -0
- package/lib/askAgent/icons.d.ts +7 -0
- package/lib/askAgent/icons.js +15 -0
- package/lib/askAgent/index.d.ts +32 -0
- package/lib/askAgent/index.js +741 -0
- package/lib/askAgent/popup.d.ts +83 -0
- package/lib/askAgent/popup.js +221 -0
- package/lib/askAgent/prompt.d.ts +24 -0
- package/lib/askAgent/prompt.js +116 -0
- package/lib/askAgent/queue.d.ts +93 -0
- package/lib/askAgent/queue.js +207 -0
- package/lib/askAgent/queuePanel.d.ts +76 -0
- package/lib/askAgent/queuePanel.js +188 -0
- package/lib/askAgent/targetPicker.d.ts +58 -0
- package/lib/askAgent/targetPicker.js +74 -0
- package/lib/askAgent/tokens.d.ts +124 -0
- package/lib/askAgent/tokens.js +13 -0
- package/lib/commandBar/index.d.ts +12 -8
- package/lib/commandBar/index.js +58 -41
- package/lib/editorBreadcrumbs/index.js +9 -4
- package/lib/editorBreadcrumbs/widget.d.ts +7 -7
- package/lib/editorBreadcrumbs/widget.js +6 -8
- package/lib/fileBrowser/commands.d.ts +2 -8
- package/lib/fileBrowser/commands.js +39 -30
- package/lib/fileBrowser/contents.d.ts +8 -3
- package/lib/fileBrowser/fileBrowser.d.ts +2 -1
- package/lib/fileBrowser/widget.d.ts +5 -9
- package/lib/fileBrowser/widget.js +1 -1
- package/lib/fileTypeIcons/index.js +5 -2
- package/lib/git/api.d.ts +0 -26
- package/lib/git/api.js +2 -44
- package/lib/git/askRequest.d.ts +23 -0
- package/lib/git/askRequest.js +90 -0
- package/lib/git/commands.d.ts +14 -2
- package/lib/git/commands.js +16 -13
- package/lib/git/diffModel.d.ts +1 -9
- package/lib/git/diffModel.js +1 -1
- package/lib/git/diffProvider.js +8 -3
- package/lib/git/diffSurface.d.ts +19 -2
- package/lib/git/diffSurface.js +64 -18
- package/lib/git/diffTheme.d.ts +0 -4
- package/lib/git/diffTheme.js +1 -1
- package/lib/git/diffWidget.d.ts +9 -0
- package/lib/git/diffWidget.js +38 -10
- package/lib/git/imageDiff.d.ts +17 -4
- package/lib/git/imageDiff.js +90 -30
- package/lib/git/index.js +7 -2
- package/lib/git/notebookDiff.d.ts +10 -67
- package/lib/git/notebookDiff.js +62 -69
- package/lib/git/tokens.d.ts +5 -2
- package/lib/highlight/index.js +12 -8
- package/lib/index.js +2 -0
- package/lib/launcher/agents.d.ts +11 -1
- package/lib/launcher/agents.js +26 -8
- package/lib/launcher/commands.d.ts +6 -2
- package/lib/launcher/dashboard.d.ts +8 -1
- package/lib/launcher/dashboard.js +39 -33
- package/lib/launcher/editorRegistry.js +5 -3
- package/lib/launcher/editors.d.ts +24 -7
- package/lib/launcher/editors.js +14 -5
- package/lib/launcher/icons.d.ts +0 -37
- package/lib/launcher/icons.js +11 -12
- package/lib/launcher/index.js +5 -2
- package/lib/launcher/invocation.d.ts +0 -15
- package/lib/launcher/invocation.js +1 -1
- package/lib/launcher/schemaDefaults.d.ts +3 -1
- package/lib/launcher/schemaDefaults.js +3 -1
- package/lib/mimeData.d.ts +7 -0
- package/lib/mimeData.js +16 -0
- package/lib/omnibox/index.d.ts +4 -0
- package/lib/omnibox/index.js +43 -2
- package/lib/omnibox/model.d.ts +43 -14
- package/lib/omnibox/model.js +117 -14
- package/lib/omnibox/recents.d.ts +65 -0
- package/lib/omnibox/recents.js +109 -0
- package/lib/omnibox/tokens.d.ts +6 -2
- package/lib/omnibox/widget.d.ts +23 -6
- package/lib/omnibox/widget.js +26 -7
- package/lib/showOutput/index.js +15 -18
- package/lib/terminals/agentTerminals.d.ts +63 -0
- package/lib/terminals/agentTerminals.js +157 -0
- package/lib/terminals/index.d.ts +7 -1
- package/lib/terminals/index.js +50 -30
- package/lib/terminals/model.d.ts +11 -2
- package/lib/terminals/model.js +27 -8
- package/lib/terminals/tokens.d.ts +66 -0
- package/lib/terminals/tokens.js +7 -0
- package/lib/terminals/widget.d.ts +3 -6
- package/lib/terminals/widget.js +1 -1
- package/lib/topBar/index.js +3 -3
- package/lib/walkthrough/index.js +14 -3
- package/lib/walkthrough/panel.d.ts +12 -4
- package/lib/walkthrough/panel.js +9 -3
- package/package.json +49 -51
- package/schema/command-bar.json +10 -0
- package/schema/launcher.json +4 -4
- package/schema/omnibox.json +15 -0
- package/src/agentSessions.ts +6 -2
- package/src/askAgent/editorSelection.ts +138 -0
- package/src/askAgent/icons.ts +16 -0
- package/src/askAgent/index.ts +915 -0
- package/src/askAgent/popup.tsx +407 -0
- package/src/askAgent/prompt.ts +144 -0
- package/src/askAgent/queue.ts +269 -0
- package/src/askAgent/queuePanel.tsx +418 -0
- package/src/askAgent/targetPicker.tsx +209 -0
- package/src/askAgent/tokens.ts +139 -0
- package/src/commandBar/index.ts +75 -49
- package/src/editorBreadcrumbs/index.ts +14 -4
- package/src/editorBreadcrumbs/widget.ts +11 -9
- package/src/fileBrowser/commands.ts +45 -31
- package/src/fileBrowser/contents.ts +7 -3
- package/src/fileBrowser/fileBrowser.tsx +1 -1
- package/src/fileBrowser/widget.tsx +5 -3
- package/src/fileTypeIcons/index.ts +6 -3
- package/src/git/api.ts +2 -61
- package/src/git/askRequest.ts +113 -0
- package/src/git/commands.ts +41 -14
- package/src/git/diffModel.ts +1 -1
- package/src/git/diffProvider.tsx +11 -3
- package/src/git/diffSurface.tsx +114 -22
- package/src/git/diffTheme.ts +1 -1
- package/src/git/diffWidget.tsx +54 -7
- package/src/git/imageDiff.tsx +169 -58
- package/src/git/index.ts +10 -2
- package/src/git/notebookDiff.tsx +91 -57
- package/src/git/tokens.ts +4 -2
- package/src/highlight/index.ts +12 -8
- package/src/index.ts +2 -0
- package/src/launcher/agents.ts +31 -7
- package/src/launcher/commands.ts +6 -2
- package/src/launcher/dashboard.tsx +86 -38
- package/src/launcher/editorRegistry.ts +10 -4
- package/src/launcher/editors.ts +34 -9
- package/src/launcher/icons.ts +11 -12
- package/src/launcher/index.ts +5 -2
- package/src/launcher/invocation.ts +1 -1
- package/src/launcher/schemaDefaults.ts +3 -1
- package/src/mimeData.ts +20 -0
- package/src/omnibox/index.ts +48 -1
- package/src/omnibox/model.ts +173 -33
- package/src/omnibox/recents.ts +155 -0
- package/src/omnibox/tokens.ts +6 -2
- package/src/omnibox/widget.tsx +54 -13
- package/src/showOutput/index.ts +20 -23
- package/src/terminals/agentTerminals.ts +238 -0
- package/src/terminals/index.ts +54 -30
- package/src/terminals/model.ts +28 -7
- package/src/terminals/tokens.ts +77 -0
- package/src/terminals/widget.tsx +4 -2
- package/src/topBar/index.ts +12 -6
- package/src/walkthrough/index.ts +19 -4
- package/src/walkthrough/panel.ts +15 -5
- package/style/askAgent.css +544 -0
- package/style/commandBar.css +12 -33
- package/style/git.css +72 -31
- package/style/index.css +1 -0
- package/style/index.js +2 -0
- package/style/topBar.css +4 -4
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import type { CommandRegistry } from '@lumino/commands';
|
|
3
|
+
import type { TranslationBundle } from '@jupyterlab/translation';
|
|
3
4
|
import { ReactWidget } from '@jupyterlab/ui-components';
|
|
4
5
|
import type { Widget } from '@lumino/widgets';
|
|
5
6
|
import type { IAgentSessions } from '../agentSessions';
|
|
@@ -12,7 +13,7 @@ import type { IEditor } from './editors';
|
|
|
12
13
|
* tab for the freshly created terminal). Keeping it as an opaque
|
|
13
14
|
* callback means the widget itself does not import `app.shell`.
|
|
14
15
|
*/
|
|
15
|
-
|
|
16
|
+
interface ILauncherDashboardOptions {
|
|
16
17
|
commands: CommandRegistry;
|
|
17
18
|
/**
|
|
18
19
|
* The agent list to render. Already filtered by availability + sorted by
|
|
@@ -48,6 +49,11 @@ export interface ILauncherDashboardOptions {
|
|
|
48
49
|
* Empty string lets the terminal extension default to the server root.
|
|
49
50
|
*/
|
|
50
51
|
cwd: string;
|
|
52
|
+
/**
|
|
53
|
+
* The translation bundle used to localize the dashboard's user-facing
|
|
54
|
+
* strings.
|
|
55
|
+
*/
|
|
56
|
+
trans: TranslationBundle;
|
|
51
57
|
}
|
|
52
58
|
/**
|
|
53
59
|
* Lumino host for the React-based launcher dashboard. Mirrors the
|
|
@@ -59,3 +65,4 @@ export declare class LauncherDashboard extends ReactWidget {
|
|
|
59
65
|
protected render(): React.ReactElement;
|
|
60
66
|
private _options;
|
|
61
67
|
}
|
|
68
|
+
export {};
|
|
@@ -33,7 +33,7 @@ const CHANGES_POLL_INTERVAL_MS = 8000;
|
|
|
33
33
|
*/
|
|
34
34
|
const CHANGES_POLL_MAX_MS = 300000;
|
|
35
35
|
function LauncherDashboardComponent(props) {
|
|
36
|
-
const { commands, agents, editor, agentSessions, onAgentLaunch, repoPath, cwd } = props;
|
|
36
|
+
const { commands, agents, editor, agentSessions, onAgentLaunch, repoPath, cwd, trans } = props;
|
|
37
37
|
const [prompt, setPrompt] = React.useState('');
|
|
38
38
|
const [git, setGit] = React.useState({
|
|
39
39
|
loading: true,
|
|
@@ -145,13 +145,13 @@ function LauncherDashboardComponent(props) {
|
|
|
145
145
|
void commands.execute(GitCommandIDs.openDiff, args);
|
|
146
146
|
}, [commands, repoPath]);
|
|
147
147
|
return (React.createElement("div", { className: "jp-xtralab-Launcher-body" },
|
|
148
|
-
React.createElement(AgentSection, { agents: agents, prompt: prompt, onPromptChange: setPrompt, onLaunch: launch }),
|
|
149
|
-
React.createElement(McpSection, { agents: agents }),
|
|
150
|
-
React.createElement(OpenSection, { editor: editor, onLaunchTerminal: launchTerminal, onLaunchNotebook: launchNotebook, onLaunchConsole: launchConsole, onLaunchEditor: launchEditor }),
|
|
151
|
-
React.createElement(ChangesSection, { git: git, onOpen: openDiff, onRefresh: () => void refresh() })));
|
|
148
|
+
React.createElement(AgentSection, { agents: agents, prompt: prompt, onPromptChange: setPrompt, onLaunch: launch, trans: trans }),
|
|
149
|
+
React.createElement(McpSection, { agents: agents, trans: trans }),
|
|
150
|
+
React.createElement(OpenSection, { editor: editor, onLaunchTerminal: launchTerminal, onLaunchNotebook: launchNotebook, onLaunchConsole: launchConsole, onLaunchEditor: launchEditor, trans: trans }),
|
|
151
|
+
React.createElement(ChangesSection, { git: git, onOpen: openDiff, onRefresh: () => void refresh(), trans: trans })));
|
|
152
152
|
}
|
|
153
153
|
function ChangesSection(props) {
|
|
154
|
-
const { git, onOpen, onRefresh } = props;
|
|
154
|
+
const { git, onOpen, onRefresh, trans } = props;
|
|
155
155
|
const files = git.result ? expandStatusFiles(git.result.files) : [];
|
|
156
156
|
// Native `<details>` rather than a hand-rolled toggle: we get the
|
|
157
157
|
// disclosure triangle, keyboard handling, and aria-expanded semantics
|
|
@@ -159,9 +159,9 @@ function ChangesSection(props) {
|
|
|
159
159
|
// we don't need to persist.
|
|
160
160
|
return (React.createElement("details", { className: "jp-xtralab-Launcher-section jp-xtralab-Launcher-changes-section", open: true },
|
|
161
161
|
React.createElement("summary", { className: "jp-xtralab-Launcher-section-summary" },
|
|
162
|
-
React.createElement("span", { className: "jp-xtralab-Launcher-section-title" },
|
|
163
|
-
files.length > 0 && (React.createElement("span", { className: "jp-xtralab-Launcher-section-count", "aria-label":
|
|
164
|
-
React.createElement("button", { type: "button", className: "jp-xtralab-Launcher-section-action", "aria-label":
|
|
162
|
+
React.createElement("span", { className: "jp-xtralab-Launcher-section-title" }, trans.__('Changes')),
|
|
163
|
+
files.length > 0 && (React.createElement("span", { className: "jp-xtralab-Launcher-section-count", "aria-label": trans._n('%1 changed file', '%1 changed files', files.length) }, files.length)),
|
|
164
|
+
React.createElement("button", { type: "button", className: "jp-xtralab-Launcher-section-action", "aria-label": trans.__('Refresh changes'),
|
|
165
165
|
// Stop the click from toggling the surrounding `<details>` —
|
|
166
166
|
// refreshing while the section is open shouldn't collapse it.
|
|
167
167
|
onClick: event => {
|
|
@@ -171,14 +171,14 @@ function ChangesSection(props) {
|
|
|
171
171
|
} },
|
|
172
172
|
React.createElement(LabIcon.resolveReact, { icon: refreshIcon, tag: "span" }))),
|
|
173
173
|
React.createElement("div", { className: "jp-xtralab-Launcher-section-body" },
|
|
174
|
-
git.loading && files.length === 0 && (React.createElement("p", { className: "jp-xtralab-Launcher-empty" },
|
|
174
|
+
git.loading && files.length === 0 && (React.createElement("p", { className: "jp-xtralab-Launcher-empty" }, trans.__('Loading…'))),
|
|
175
175
|
!git.loading && git.error !== null && (React.createElement("p", { className: "jp-xtralab-Launcher-empty" }, git.error)),
|
|
176
|
-
!git.loading && git.error === null && files.length === 0 && (React.createElement("p", { className: "jp-xtralab-Launcher-empty" },
|
|
176
|
+
!git.loading && git.error === null && files.length === 0 && (React.createElement("p", { className: "jp-xtralab-Launcher-empty" }, trans.__('No changes.'))),
|
|
177
177
|
files.length > 0 && (React.createElement("ul", { className: "jp-xtralab-Launcher-changes" }, files.map((change, index) => (React.createElement("li", { key: `${change.group}:${change.path}:${index}` },
|
|
178
|
-
React.createElement("button", { type: "button", className: "jp-xtralab-Launcher-change", onClick: () => onOpen(change), title:
|
|
178
|
+
React.createElement("button", { type: "button", className: "jp-xtralab-Launcher-change", onClick: () => onOpen(change), title: trans.__('Open diff for %1', change.path) },
|
|
179
179
|
React.createElement("span", { className: `jp-xtralab-Launcher-change-badge jp-xtralab-Launcher-change-${change.status}`, "aria-hidden": "true" }, statusBadge(change.status)),
|
|
180
180
|
React.createElement("span", { className: "jp-xtralab-Launcher-change-path" }, change.path),
|
|
181
|
-
React.createElement("span", { className: "jp-xtralab-Launcher-change-group", "aria-hidden": "true" }, change.group === 'staged' ? 'staged' : ''))))))))));
|
|
181
|
+
React.createElement("span", { className: "jp-xtralab-Launcher-change-group", "aria-hidden": "true" }, change.group === 'staged' ? trans.__('staged') : ''))))))))));
|
|
182
182
|
}
|
|
183
183
|
function statusBadge(status) {
|
|
184
184
|
switch (status) {
|
|
@@ -202,7 +202,7 @@ function statusBadge(status) {
|
|
|
202
202
|
}
|
|
203
203
|
function AgentSection(props) {
|
|
204
204
|
var _a;
|
|
205
|
-
const { agents, prompt, onPromptChange, onLaunch } = props;
|
|
205
|
+
const { agents, prompt, onPromptChange, onLaunch, trans } = props;
|
|
206
206
|
const trimmed = prompt.trim();
|
|
207
207
|
const promptActive = trimmed.length > 0;
|
|
208
208
|
// The first prompt-capable agent is what Cmd/Ctrl+Enter fires; the hint
|
|
@@ -211,8 +211,8 @@ function AgentSection(props) {
|
|
|
211
211
|
const primaryAgent = agents.find(agent => agent.promptArgs !== undefined);
|
|
212
212
|
const hintId = 'jp-xtralab-Launcher-agent-hint';
|
|
213
213
|
return (React.createElement("section", { className: "jp-xtralab-Launcher-section" },
|
|
214
|
-
React.createElement("h2", { className: "jp-xtralab-Launcher-section-title" },
|
|
215
|
-
React.createElement("textarea", { className: "jp-xtralab-Launcher-prompt", placeholder:
|
|
214
|
+
React.createElement("h2", { className: "jp-xtralab-Launcher-section-title" }, trans.__('Start an agent')),
|
|
215
|
+
React.createElement("textarea", { className: "jp-xtralab-Launcher-prompt", placeholder: trans.__('Initial prompt (optional) — passed to the selected agent.'), value: prompt, spellCheck: false, rows: 3, onChange: event => onPromptChange(event.target.value), onKeyDown: event => {
|
|
216
216
|
if (event.key === 'Enter' &&
|
|
217
217
|
(event.metaKey || event.ctrlKey) &&
|
|
218
218
|
trimmed.length > 0 &&
|
|
@@ -222,13 +222,13 @@ function AgentSection(props) {
|
|
|
222
222
|
}
|
|
223
223
|
} }),
|
|
224
224
|
React.createElement("p", { id: hintId, className: "jp-xtralab-Launcher-agent-hint", "aria-live": "polite" }, promptActive
|
|
225
|
-
?
|
|
226
|
-
: 'Type a prompt to send it to the chosen agent. Some agents only launch without a prompt.'),
|
|
225
|
+
? trans.__("Cmd/Ctrl+Enter launches %1. Agents that don't accept an initial prompt are dimmed.", (_a = primaryAgent === null || primaryAgent === void 0 ? void 0 : primaryAgent.label) !== null && _a !== void 0 ? _a : trans.__('the first prompt-capable agent'))
|
|
226
|
+
: trans.__('Type a prompt to send it to the chosen agent. Some agents only launch without a prompt.')),
|
|
227
227
|
React.createElement("div", { className: "jp-xtralab-Launcher-agents" }, agents.map(agent => {
|
|
228
228
|
const supportsPrompt = agent.promptArgs !== undefined;
|
|
229
229
|
const disabled = promptActive && !supportsPrompt;
|
|
230
230
|
const tooltip = disabled
|
|
231
|
-
?
|
|
231
|
+
? trans.__("%1 doesn't accept an initial prompt — clear the prompt to launch.", agent.label)
|
|
232
232
|
: agent.caption;
|
|
233
233
|
return (React.createElement("button", { key: agent.id, type: "button", className: "jp-xtralab-Launcher-agent", title: tooltip, "aria-label": agent.label, "aria-describedby": hintId, disabled: disabled, onClick: () => onLaunch(agent) },
|
|
234
234
|
React.createElement(LabIcon.resolveReact, { icon: agent.icon, tag: "span", className: "jp-xtralab-Launcher-agent-icon" }),
|
|
@@ -242,7 +242,9 @@ function AgentSection(props) {
|
|
|
242
242
|
* there is no one-line command to surface for them.
|
|
243
243
|
*/
|
|
244
244
|
const MCP_ADD_AGENT_IDS = new Set(['claude', 'codex', 'copilot']);
|
|
245
|
-
/**
|
|
245
|
+
/**
|
|
246
|
+
* The stdio proxy console script that bridges an agent to the MCP server.
|
|
247
|
+
*/
|
|
246
248
|
const MCP_PROXY_COMMAND = 'jupyter-server-mcp-proxy';
|
|
247
249
|
/**
|
|
248
250
|
* Copy `text` to the clipboard via a hidden, selected `<textarea>` and the
|
|
@@ -279,6 +281,7 @@ function legacyCopy(text) {
|
|
|
279
281
|
* of those agents are on `$PATH`.
|
|
280
282
|
*/
|
|
281
283
|
function McpSection(props) {
|
|
284
|
+
const { trans } = props;
|
|
282
285
|
const [copiedId, setCopiedId] = React.useState(null);
|
|
283
286
|
const registerable = props.agents.filter(agent => MCP_ADD_AGENT_IDS.has(agent.id));
|
|
284
287
|
if (registerable.length === 0) {
|
|
@@ -306,22 +309,25 @@ function McpSection(props) {
|
|
|
306
309
|
};
|
|
307
310
|
return (React.createElement("details", { className: "jp-xtralab-Launcher-section jp-xtralab-Launcher-mcp-section" },
|
|
308
311
|
React.createElement("summary", { className: "jp-xtralab-Launcher-section-summary" },
|
|
309
|
-
React.createElement("span", { className: "jp-xtralab-Launcher-section-title" },
|
|
312
|
+
React.createElement("span", { className: "jp-xtralab-Launcher-section-title" }, trans.__('Connect agents to JupyterLab (MCP)'))),
|
|
310
313
|
React.createElement("div", { className: "jp-xtralab-Launcher-section-body" },
|
|
311
|
-
React.createElement("p", { className: "jp-xtralab-Launcher-agent-hint" },
|
|
314
|
+
React.createElement("p", { className: "jp-xtralab-Launcher-agent-hint" }, trans.__('Run once per agent to let it drive this JupyterLab over MCP. No port needed — the proxy finds this server on its own.')),
|
|
312
315
|
React.createElement("ul", { className: "jp-xtralab-Launcher-mcp-list" }, registerable.map(agent => {
|
|
313
316
|
const command = `${agent.command} mcp add jupyter -- ${MCP_PROXY_COMMAND}`;
|
|
314
317
|
return (React.createElement("li", { key: agent.id, className: "jp-xtralab-Launcher-mcp-item" },
|
|
315
318
|
React.createElement("code", { className: "jp-xtralab-Launcher-mcp-command" }, command),
|
|
316
319
|
React.createElement("button", { type: "button", className: copiedId === agent.id
|
|
317
320
|
? 'jp-xtralab-Launcher-mcp-copy jp-mod-copied'
|
|
318
|
-
: 'jp-xtralab-Launcher-mcp-copy', "aria-label":
|
|
321
|
+
: 'jp-xtralab-Launcher-mcp-copy', "aria-label": trans.__('Copy the %1 command', agent.label), onClick: () => copy(command, agent.id) }, copiedId === agent.id
|
|
322
|
+
? trans.__('Copied!')
|
|
323
|
+
: trans.__('Copy'))));
|
|
319
324
|
})),
|
|
320
325
|
React.createElement("p", { className: "jp-xtralab-Launcher-mcp-note" },
|
|
321
|
-
|
|
326
|
+
trans.__('Other agents (Goose, OpenCode, Kiro, Mistral Vibe, Antigravity) register MCP through their own config — point them at the same'),
|
|
322
327
|
' ',
|
|
323
328
|
React.createElement("code", null, MCP_PROXY_COMMAND),
|
|
324
|
-
"
|
|
329
|
+
" ",
|
|
330
|
+
trans.__('command.')))));
|
|
325
331
|
}
|
|
326
332
|
/**
|
|
327
333
|
* The non-agent launch tiles — a plain terminal, a new notebook, and a
|
|
@@ -336,19 +342,19 @@ function McpSection(props) {
|
|
|
336
342
|
* renders.
|
|
337
343
|
*/
|
|
338
344
|
function OpenSection(props) {
|
|
339
|
-
const { editor, onLaunchTerminal, onLaunchNotebook, onLaunchConsole, onLaunchEditor } = props;
|
|
345
|
+
const { editor, onLaunchTerminal, onLaunchNotebook, onLaunchConsole, onLaunchEditor, trans } = props;
|
|
340
346
|
return (React.createElement("section", { className: "jp-xtralab-Launcher-section" },
|
|
341
|
-
React.createElement("h2", { className: "jp-xtralab-Launcher-section-title" },
|
|
347
|
+
React.createElement("h2", { className: "jp-xtralab-Launcher-section-title" }, trans.__('Open')),
|
|
342
348
|
React.createElement("div", { className: "jp-xtralab-Launcher-agents" },
|
|
343
|
-
React.createElement("button", { type: "button", className: "jp-xtralab-Launcher-agent", title:
|
|
349
|
+
React.createElement("button", { type: "button", className: "jp-xtralab-Launcher-agent", title: trans.__('Open a new terminal.'), "aria-label": trans.__('Open a new terminal'), onClick: onLaunchTerminal },
|
|
344
350
|
React.createElement(LabIcon.resolveReact, { icon: terminalIcon, tag: "span", className: "jp-xtralab-Launcher-agent-icon" }),
|
|
345
|
-
React.createElement("span", { className: "jp-xtralab-Launcher-agent-label" },
|
|
346
|
-
React.createElement("button", { type: "button", className: "jp-xtralab-Launcher-agent", title:
|
|
351
|
+
React.createElement("span", { className: "jp-xtralab-Launcher-agent-label" }, trans.__('Terminal'))),
|
|
352
|
+
React.createElement("button", { type: "button", className: "jp-xtralab-Launcher-agent", title: trans.__('Create a new notebook.'), "aria-label": trans.__('Create a new notebook'), onClick: onLaunchNotebook },
|
|
347
353
|
React.createElement(LabIcon.resolveReact, { icon: notebookIcon, tag: "span", className: "jp-xtralab-Launcher-agent-icon" }),
|
|
348
|
-
React.createElement("span", { className: "jp-xtralab-Launcher-agent-label" },
|
|
349
|
-
React.createElement("button", { type: "button", className: "jp-xtralab-Launcher-agent", title:
|
|
354
|
+
React.createElement("span", { className: "jp-xtralab-Launcher-agent-label" }, trans.__('Notebook'))),
|
|
355
|
+
React.createElement("button", { type: "button", className: "jp-xtralab-Launcher-agent", title: trans.__('Create a new console.'), "aria-label": trans.__('Create a new console'), onClick: onLaunchConsole },
|
|
350
356
|
React.createElement(LabIcon.resolveReact, { icon: consoleIcon, tag: "span", className: "jp-xtralab-Launcher-agent-icon" }),
|
|
351
|
-
React.createElement("span", { className: "jp-xtralab-Launcher-agent-label" },
|
|
357
|
+
React.createElement("span", { className: "jp-xtralab-Launcher-agent-label" }, trans.__('Console'))),
|
|
352
358
|
editor && (React.createElement("button", { type: "button", className: "jp-xtralab-Launcher-agent", title: editor.caption, "aria-label": editor.caption, onClick: onLaunchEditor },
|
|
353
359
|
React.createElement(LabIcon.resolveReact, { icon: editor.icon, tag: "span", className: "jp-xtralab-Launcher-agent-icon" }),
|
|
354
360
|
React.createElement("span", { className: "jp-xtralab-Launcher-agent-label" }, editor.label))))));
|
|
@@ -29,7 +29,9 @@ class EditorRegistry {
|
|
|
29
29
|
get changed() {
|
|
30
30
|
return this._changed;
|
|
31
31
|
}
|
|
32
|
-
/**
|
|
32
|
+
/**
|
|
33
|
+
* Replace both lists (recomputed together) and notify observers.
|
|
34
|
+
*/
|
|
33
35
|
set(editors, current) {
|
|
34
36
|
this._editors = editors;
|
|
35
37
|
this._current = current;
|
|
@@ -57,9 +59,9 @@ export const editorRegistryPlugin = {
|
|
|
57
59
|
// Probe only the editors that opt into the availability check; entries
|
|
58
60
|
// with `requireAvailable: false` (e.g. a shell alias) are shown
|
|
59
61
|
// regardless and don't need a `which` lookup.
|
|
60
|
-
const probe = editors
|
|
62
|
+
const probe = Array.from(new Set(editors
|
|
61
63
|
.filter(editor => editor.requireAvailable)
|
|
62
|
-
.map(editor => editor.command);
|
|
64
|
+
.map(editor => editor.command)));
|
|
63
65
|
const available = await fetchAvailableCommands(probe);
|
|
64
66
|
registry.set(editors, resolveEditor(editors, available));
|
|
65
67
|
};
|
|
@@ -7,15 +7,25 @@ import { LabIcon } from '@jupyterlab/ui-components';
|
|
|
7
7
|
* the terminals panel to badge running editors.
|
|
8
8
|
*/
|
|
9
9
|
export interface IEditor {
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Stable id; also the default `$PATH` command probed for availability.
|
|
12
|
+
*/
|
|
11
13
|
id: string;
|
|
12
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* Tile label, e.g. "Neovim".
|
|
16
|
+
*/
|
|
13
17
|
label: string;
|
|
14
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* Tile tooltip.
|
|
20
|
+
*/
|
|
15
21
|
caption: string;
|
|
16
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* The literal command typed into the new terminal, e.g. `nvim`.
|
|
24
|
+
*/
|
|
17
25
|
command: string;
|
|
18
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Brand icon for the tile.
|
|
28
|
+
*/
|
|
19
29
|
icon: LabIcon;
|
|
20
30
|
/**
|
|
21
31
|
* Preference order for the single launcher tile: the first candidate, by
|
|
@@ -53,7 +63,12 @@ export interface IEditorSettings {
|
|
|
53
63
|
* the editor tile entirely. Defaults to true.
|
|
54
64
|
*/
|
|
55
65
|
enabled?: boolean;
|
|
56
|
-
/**
|
|
66
|
+
/**
|
|
67
|
+
* See {@link IEditor.requireAvailable}. Defaults to true for a built-in
|
|
68
|
+
* editor that still uses its shipped command, and to false once you override
|
|
69
|
+
* the `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.
|
|
71
|
+
*/
|
|
57
72
|
requireAvailable?: boolean;
|
|
58
73
|
}
|
|
59
74
|
/**
|
|
@@ -69,7 +84,9 @@ export declare function defaultEditorSettings(): IEditorSettings[];
|
|
|
69
84
|
* entries keep their fields unless explicitly overridden; user-only entries are
|
|
70
85
|
* appended. `enabled: false` filters an entry out of the result entirely (so
|
|
71
86
|
* callers don't need to re-check the flag). The result is sorted by rank, which
|
|
72
|
-
* is also the launcher's tile-preference order. Mirrors `mergeAgents
|
|
87
|
+
* is also the launcher's tile-preference order. Mirrors `mergeAgents`, including
|
|
88
|
+
* turning `requireAvailable` off when the user overrides a built-in's `command`
|
|
89
|
+
* so an aliased editor still shows.
|
|
73
90
|
*/
|
|
74
91
|
export declare function mergeEditors(overrides: IEditorSettings[]): IEditor[];
|
|
75
92
|
/**
|
package/lib/launcher/editors.js
CHANGED
|
@@ -58,7 +58,9 @@ function resolveEditorIcon(id, iconSvg) {
|
|
|
58
58
|
* entries keep their fields unless explicitly overridden; user-only entries are
|
|
59
59
|
* appended. `enabled: false` filters an entry out of the result entirely (so
|
|
60
60
|
* callers don't need to re-check the flag). The result is sorted by rank, which
|
|
61
|
-
* is also the launcher's tile-preference order. Mirrors `mergeAgents
|
|
61
|
+
* is also the launcher's tile-preference order. Mirrors `mergeAgents`, including
|
|
62
|
+
* turning `requireAvailable` off when the user overrides a built-in's `command`
|
|
63
|
+
* so an aliased editor still shows.
|
|
62
64
|
*/
|
|
63
65
|
export function mergeEditors(overrides) {
|
|
64
66
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
@@ -74,16 +76,23 @@ export function mergeEditors(overrides) {
|
|
|
74
76
|
if (override.enabled === false) {
|
|
75
77
|
continue;
|
|
76
78
|
}
|
|
79
|
+
const command = (_a = override.command) !== null && _a !== void 0 ? _a : base.command;
|
|
77
80
|
merged.push({
|
|
78
81
|
id: base.id,
|
|
79
|
-
label: (
|
|
80
|
-
caption: (
|
|
81
|
-
command
|
|
82
|
+
label: (_b = override.label) !== null && _b !== void 0 ? _b : base.label,
|
|
83
|
+
caption: (_c = override.caption) !== null && _c !== void 0 ? _c : base.caption,
|
|
84
|
+
command,
|
|
82
85
|
icon: override.iconSvg
|
|
83
86
|
? resolveEditorIcon(base.id, override.iconSvg)
|
|
84
87
|
: base.icon,
|
|
85
88
|
rank: (_d = override.rank) !== null && _d !== void 0 ? _d : base.rank,
|
|
86
|
-
|
|
89
|
+
// See `mergeAgents`: once the user points a built-in editor at their own
|
|
90
|
+
// command (e.g. a shell alias `which` can't resolve), stop requiring
|
|
91
|
+
// availability so the tile still shows. The check stays on only while the
|
|
92
|
+
// command is xtralab's default.
|
|
93
|
+
requireAvailable: command === base.command
|
|
94
|
+
? ((_e = override.requireAvailable) !== null && _e !== void 0 ? _e : base.requireAvailable)
|
|
95
|
+
: false
|
|
87
96
|
});
|
|
88
97
|
}
|
|
89
98
|
// What remains in `overrideById` are ids that don't match a built-in — treat
|
package/lib/launcher/icons.d.ts
CHANGED
|
@@ -1,41 +1,4 @@
|
|
|
1
1
|
import { LabIcon } from '@jupyterlab/ui-components';
|
|
2
|
-
/**
|
|
3
|
-
* Brand icons for the agent launcher cards. Most marks are taken verbatim
|
|
4
|
-
* from `jupyter-ai-contrib/jupyter-ai-acp-client`
|
|
5
|
-
* (`jupyter_ai_acp_client/static/*.svg`, BSD-3-Clause); Antigravity post-dates
|
|
6
|
-
* that set, so its mark is the official glyph from `@lobehub/icons-static-svg`
|
|
7
|
-
* (MIT) — we ship the brand-colored `antigravity-color` variant so Antigravity
|
|
8
|
-
* reads as a multi-color Google mark, occupying the slot the Gemini icon used
|
|
9
|
-
* to fill before the upstream Gemini CLI sunset. Small adjustments are applied
|
|
10
|
-
* to play nicely with JupyterLab themes:
|
|
11
|
-
* - Monochrome marks (Codex, Copilot, Goose) use `currentColor` so they
|
|
12
|
-
* inherit the surrounding launcher card's text color rather than
|
|
13
|
-
* hard-coding black, which disappears on the dark theme.
|
|
14
|
-
* - The Goose mark upstream is rendered on a white rounded rect; we drop
|
|
15
|
-
* the rect so the silhouette can sit on the launcher card directly.
|
|
16
|
-
* - SVG ids that would collide if two copies of the same artwork ended up
|
|
17
|
-
* on the page (gradient/mask/filter defs) are namespaced under
|
|
18
|
-
* `xtralab-…`.
|
|
19
|
-
*
|
|
20
|
-
* Brand-colored icons (Antigravity, Claude, Kiro, Mistral Vibe, OpenCode) keep
|
|
21
|
-
* their upstream colors; the dark/light contrast of the launcher card behind
|
|
22
|
-
* them is the same as on `jupyter-ai-acp-client`.
|
|
23
|
-
*
|
|
24
|
-
* The Vim and Neovim marks belong to the launcher's "Open" editor tile rather
|
|
25
|
-
* than the agent grid. They are the brand silhouettes from Simple Icons
|
|
26
|
-
* (https://simpleicons.org, CC0), each filled with its brand green so the mark
|
|
27
|
-
* reads on both the light and dark themes.
|
|
28
|
-
*/
|
|
29
|
-
export declare const antigravityIcon: LabIcon;
|
|
30
|
-
export declare const claudeIcon: LabIcon;
|
|
31
|
-
export declare const codexIcon: LabIcon;
|
|
32
|
-
export declare const copilotIcon: LabIcon;
|
|
33
|
-
export declare const gooseIcon: LabIcon;
|
|
34
|
-
export declare const kiroIcon: LabIcon;
|
|
35
|
-
export declare const mistralVibeIcon: LabIcon;
|
|
36
|
-
export declare const opencodeIcon: LabIcon;
|
|
37
|
-
export declare const neovimIcon: LabIcon;
|
|
38
|
-
export declare const vimIcon: LabIcon;
|
|
39
2
|
/**
|
|
40
3
|
* Built-in icons keyed by the agent's id, used to resolve the icon for an
|
|
41
4
|
* agent declared without an inline `iconSvg` override (i.e. one of xtralab's
|
package/lib/launcher/icons.js
CHANGED
|
@@ -5,8 +5,7 @@ import { LabIcon } from '@jupyterlab/ui-components';
|
|
|
5
5
|
* (`jupyter_ai_acp_client/static/*.svg`, BSD-3-Clause); Antigravity post-dates
|
|
6
6
|
* that set, so its mark is the official glyph from `@lobehub/icons-static-svg`
|
|
7
7
|
* (MIT) — we ship the brand-colored `antigravity-color` variant so Antigravity
|
|
8
|
-
* reads as a multi-color Google mark
|
|
9
|
-
* to fill before the upstream Gemini CLI sunset. Small adjustments are applied
|
|
8
|
+
* reads as a multi-color Google mark. Small adjustments are applied
|
|
10
9
|
* to play nicely with JupyterLab themes:
|
|
11
10
|
* - Monochrome marks (Codex, Copilot, Goose) use `currentColor` so they
|
|
12
11
|
* inherit the surrounding launcher card's text color rather than
|
|
@@ -26,7 +25,7 @@ import { LabIcon } from '@jupyterlab/ui-components';
|
|
|
26
25
|
* (https://simpleicons.org, CC0), each filled with its brand green so the mark
|
|
27
26
|
* reads on both the light and dark themes.
|
|
28
27
|
*/
|
|
29
|
-
|
|
28
|
+
const antigravityIcon = new LabIcon({
|
|
30
29
|
name: 'xtralab:agent-antigravity',
|
|
31
30
|
svgstr: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none">
|
|
32
31
|
<mask id="xtralab-antigravity-mask" height="23" maskUnits="userSpaceOnUse" width="24" x="0" y="1">
|
|
@@ -104,26 +103,26 @@ export const antigravityIcon = new LabIcon({
|
|
|
104
103
|
</defs>
|
|
105
104
|
</svg>`
|
|
106
105
|
});
|
|
107
|
-
|
|
106
|
+
const claudeIcon = new LabIcon({
|
|
108
107
|
name: 'xtralab:agent-claude',
|
|
109
108
|
svgstr: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 1200">
|
|
110
109
|
<path fill="#d97757" d="M 233.959793 800.214905 L 468.644287 668.536987 L 472.590637 657.100647 L 468.644287 650.738403 L 457.208069 650.738403 L 417.986633 648.322144 L 283.892639 644.69812 L 167.597321 639.865845 L 54.926208 633.825623 L 26.577238 627.785339 L 3.3e-05 592.751709 L 2.73832 575.27533 L 26.577238 559.248352 L 60.724873 562.228149 L 136.187973 567.382629 L 249.422867 575.194763 L 331.570496 580.026978 L 453.261841 592.671082 L 472.590637 592.671082 L 475.328857 584.859009 L 468.724915 580.026978 L 463.570557 575.194763 L 346.389313 495.785217 L 219.543671 411.865906 L 153.100723 363.543762 L 117.181267 339.060425 L 99.060455 316.107361 L 91.248367 266.01355 L 123.865784 230.093994 L 167.677887 233.073853 L 178.872513 236.053772 L 223.248367 270.201477 L 318.040283 343.570496 L 441.825592 434.738342 L 459.946411 449.798706 L 467.194672 444.64447 L 468.080597 441.020203 L 459.946411 427.409485 L 392.617493 305.718323 L 320.778564 181.932983 L 288.80542 130.630859 L 280.348999 99.865845 C 277.369171 87.221436 275.194641 76.590698 275.194641 63.624268 L 312.322174 13.20813 L 332.8591 6.604126 L 382.389313 13.20813 L 403.248352 31.328979 L 434.013519 101.71814 L 483.865753 212.537048 L 561.181274 363.221497 L 583.812134 407.919434 L 595.892639 449.315491 L 600.40271 461.959839 L 608.214783 461.959839 L 608.214783 454.711609 L 614.577271 369.825623 L 626.335632 265.61084 L 637.771851 131.516846 L 641.718201 93.745117 L 660.402832 48.483276 L 697.530334 24.000122 L 726.52356 37.852417 L 750.362549 72 L 747.060486 94.067139 L 732.886047 186.201416 L 705.100708 330.52356 L 686.979919 427.167847 L 697.530334 427.167847 L 709.61084 415.087341 L 758.496704 350.174561 L 840.644348 247.490051 L 876.885925 206.738342 L 919.167847 161.71814 L 946.308838 140.29541 L 997.61084 140.29541 L 1035.38269 196.429626 L 1018.469849 254.416199 L 965.637634 321.422852 L 921.825562 378.201538 L 859.006714 462.765259 L 819.785278 530.41626 L 823.409424 535.812073 L 832.75177 534.92627 L 974.657776 504.724915 L 1051.328979 490.872559 L 1142.818848 475.167786 L 1184.214844 494.496582 L 1188.724854 514.147644 L 1172.456421 554.335693 L 1074.604126 578.496765 L 959.838989 601.449829 L 788.939636 641.879272 L 786.845764 643.409485 L 789.261841 646.389343 L 866.255127 653.637634 L 899.194702 655.409424 L 979.812134 655.409424 L 1129.932861 666.604187 L 1169.154419 692.537109 L 1192.671265 724.268677 L 1188.724854 748.429688 L 1128.322144 779.194641 L 1046.818848 759.865845 L 856.590759 714.604126 L 791.355774 698.335754 L 782.335693 698.335754 L 782.335693 703.731567 L 836.69812 756.885986 L 936.322205 846.845581 L 1061.073975 962.81897 L 1067.436279 991.490112 L 1051.409424 1014.120911 L 1034.496704 1011.704712 L 924.885986 929.234924 L 882.604126 892.107544 L 786.845764 811.48999 L 780.483276 811.48999 L 780.483276 819.946289 L 802.550415 852.241699 L 919.087341 1027.409424 L 925.127625 1081.127686 L 916.671204 1098.604126 L 886.469849 1109.154419 L 853.288696 1103.114136 L 785.073914 1007.355835 L 714.684631 899.516785 L 657.906067 802.872498 L 650.979858 806.81897 L 617.476624 1167.704834 L 601.771851 1186.147705 L 565.530212 1200 L 535.328857 1177.046997 L 519.302124 1139.919556 L 535.328857 1066.550537 L 554.657776 970.792053 L 570.362488 894.68457 L 584.536926 800.134277 L 592.993347 768.724976 L 592.429626 766.630859 L 585.503479 767.516968 L 514.22821 865.369263 L 405.825531 1011.865906 L 320.053711 1103.677979 L 299.516815 1111.812256 L 263.919525 1093.369263 L 267.221497 1060.429688 L 287.114136 1031.114136 L 405.825531 880.107361 L 477.422913 786.52356 L 523.651062 732.483276 L 523.328918 724.671265 L 520.590698 724.671265 L 205.288605 929.395935 L 149.154434 936.644409 L 124.993355 914.01355 L 127.973183 876.885986 L 139.409409 864.80542 L 234.201385 799.570435 L 233.879227 799.8927 Z"/>
|
|
111
110
|
</svg>`
|
|
112
111
|
});
|
|
113
|
-
|
|
112
|
+
const codexIcon = new LabIcon({
|
|
114
113
|
name: 'xtralab:agent-codex',
|
|
115
114
|
svgstr: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none">
|
|
116
115
|
<path stroke="currentColor" stroke-linecap="round" stroke-width="2.484" d="M22.356 19.797H17.17M9.662 12.29l1.979 3.576a.511.511 0 0 1-.005.504l-1.974 3.409M30.758 16c0 8.15-6.607 14.758-14.758 14.758-8.15 0-14.758-6.607-14.758-14.758C1.242 7.85 7.85 1.242 16 1.242c8.15 0 14.758 6.608 14.758 14.758Z"/>
|
|
117
116
|
</svg>`
|
|
118
117
|
});
|
|
119
|
-
|
|
118
|
+
const copilotIcon = new LabIcon({
|
|
120
119
|
name: 'xtralab:agent-copilot',
|
|
121
120
|
svgstr: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor">
|
|
122
121
|
<path d="M7.998 15.035c-4.562 0-7.873-2.914-7.998-3.749V9.338c.085-.628.677-1.686 1.588-2.065.013-.07.024-.143.036-.218.029-.183.06-.384.126-.612-.201-.508-.254-1.084-.254-1.656 0-.87.128-1.769.693-2.484.579-.733 1.494-1.124 2.724-1.261 1.206-.134 2.262.034 2.944.765.05.053.096.108.139.165.044-.057.094-.112.143-.165.682-.731 1.738-.899 2.944-.765 1.23.137 2.145.528 2.724 1.261.566.715.693 1.614.693 2.484 0 .572-.053 1.148-.254 1.656.066.228.098.429.126.612.012.076.024.148.037.218.924.385 1.522 1.471 1.591 2.095v1.872c0 .766-3.351 3.795-8.002 3.795Zm0-1.485c2.28 0 4.584-1.11 5.002-1.433V7.862l-.023-.116c-.49.21-1.075.291-1.727.291-1.146 0-2.059-.327-2.71-.991A3.222 3.222 0 0 1 8 6.303a3.24 3.24 0 0 1-.544.743c-.65.664-1.563.991-2.71.991-.652 0-1.236-.081-1.727-.291l-.023.116v4.255c.419.323 2.722 1.433 5.002 1.433ZM6.762 2.83c-.193-.206-.637-.413-1.682-.297-1.019.113-1.479.404-1.713.7-.247.312-.369.789-.369 1.554 0 .793.129 1.171.308 1.371.162.181.519.379 1.442.379.853 0 1.339-.235 1.638-.54.315-.322.527-.827.617-1.553.117-.935-.037-1.395-.241-1.614Zm4.155-.297c-1.044-.116-1.488.091-1.681.297-.204.219-.359.679-.242 1.614.091.726.303 1.231.618 1.553.299.305.784.54 1.638.54.922 0 1.28-.198 1.442-.379.179-.2.308-.578.308-1.371 0-.765-.123-1.242-.37-1.554-.233-.296-.693-.587-1.713-.7Z"/>
|
|
123
122
|
<path d="M6.25 9.037a.75.75 0 0 1 .75.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 .75-.75Zm4.25.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 1.5 0Z"/>
|
|
124
123
|
</svg>`
|
|
125
124
|
});
|
|
126
|
-
|
|
125
|
+
const gooseIcon = new LabIcon({
|
|
127
126
|
name: 'xtralab:agent-goose',
|
|
128
127
|
svgstr: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2048 2048">
|
|
129
128
|
<g transform="translate(128, 94) scale(3)" fill="currentColor">
|
|
@@ -131,7 +130,7 @@ export const gooseIcon = new LabIcon({
|
|
|
131
130
|
</g>
|
|
132
131
|
</svg>`
|
|
133
132
|
});
|
|
134
|
-
|
|
133
|
+
const kiroIcon = new LabIcon({
|
|
135
134
|
name: 'xtralab:agent-kiro',
|
|
136
135
|
svgstr: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 1200" fill="none">
|
|
137
136
|
<rect width="1200" height="1200" rx="260" fill="#9046FF"/>
|
|
@@ -145,7 +144,7 @@ export const kiroIcon = new LabIcon({
|
|
|
145
144
|
</g>
|
|
146
145
|
</svg>`
|
|
147
146
|
});
|
|
148
|
-
|
|
147
|
+
const mistralVibeIcon = new LabIcon({
|
|
149
148
|
name: 'xtralab:agent-mistral-vibe',
|
|
150
149
|
svgstr: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="none">
|
|
151
150
|
<g transform="translate(48 71) scale(0.84)">
|
|
@@ -162,7 +161,7 @@ export const mistralVibeIcon = new LabIcon({
|
|
|
162
161
|
</g>
|
|
163
162
|
</svg>`
|
|
164
163
|
});
|
|
165
|
-
|
|
164
|
+
const opencodeIcon = new LabIcon({
|
|
166
165
|
name: 'xtralab:agent-opencode',
|
|
167
166
|
svgstr: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="none">
|
|
168
167
|
<rect width="512" height="512" fill="#131010"/>
|
|
@@ -170,13 +169,13 @@ export const opencodeIcon = new LabIcon({
|
|
|
170
169
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M384 416H128V96H384V416ZM320 160H192V352H320V160Z" fill="white"/>
|
|
171
170
|
</svg>`
|
|
172
171
|
});
|
|
173
|
-
|
|
172
|
+
const neovimIcon = new LabIcon({
|
|
174
173
|
name: 'xtralab:editor-neovim',
|
|
175
174
|
svgstr: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#57A143">
|
|
176
175
|
<path d="M2.214 4.954v13.615L7.655 24V10.314L3.312 3.845 2.214 4.954zm4.999 17.98l-4.557-4.548V5.136l.59-.596 3.967 5.908v12.485zm14.573-4.457l-.862.937-4.24-6.376V0l5.068 5.092.034 13.385zM7.431.001l12.998 19.835-3.637 3.637L3.787 3.683 7.43 0z"/>
|
|
177
176
|
</svg>`
|
|
178
177
|
});
|
|
179
|
-
|
|
178
|
+
const vimIcon = new LabIcon({
|
|
180
179
|
name: 'xtralab:editor-vim',
|
|
181
180
|
svgstr: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#019733">
|
|
182
181
|
<path d="M24 11.986h-.027l-4.318-4.318 4.303-4.414V1.461l-.649-.648h-8.198l-.66.605v1.045L12.015.027V0L12 .014 11.986 0v.027l-1.29 1.291-.538-.539H2.035l-.638.692v1.885l.616.616h.72v5.31L.027 11.987H0L.014 12 0 12.014h.027l2.706 2.706v6.467l.907.523h2.322l1.857-1.904 4.166 4.166V24l.015-.014.014.014v-.028l2.51-2.509h.485c.111 0 .211-.07.25-.179l.146-.426c.028-.084.012-.172-.037-.239l1.462-1.462-.612 1.962c-.043.141.036.289.177.332.025.008.052.012.078.012h1.824c.106-.001.201-.064.243-.163l.165-.394c.025-.065.024-.138-.004-.203-.027-.065-.08-.116-.146-.142-.029-.012-.062-.019-.097-.02h-.075l.84-2.644h1.232l-1.016 3.221c-.043.141.036.289.176.332.025.008.052.012.079.012h2.002c.11 0 .207-.066.248-.17l.164-.428c.051-.138-.021-.29-.158-.341-.029-.011-.06-.017-.091-.017h-.145l1.131-3.673c.027-.082.012-.173-.039-.24l-.375-.504-.003-.005c-.051-.064-.127-.102-.209-.102h-1.436c-.071 0-.141.03-.19.081l-.4.439h-.624l-.042-.046 4.445-4.445H24L23.986 12l.014-.014zM9.838 21.139l1.579-4.509h-.501l.297-.304h1.659l-1.563 4.555h.623l-.079.258H9.838zm3.695-7.516l.15.151-.269.922-.225.226h-.969l-.181-.181.311-.871.288-.247h.895zM5.59 20.829H3.877l-.262-.15V3.091H2.379l-.1-.1V1.815l.143-.154h7.371l.213.214v1.108l-.142.173H8.785v8.688l8.807-8.688h-2.086l-.175-.188V1.805l.121-.111h7.49l.132.133v1.07L12.979 13.25h-.373c-.015-.001-.028 0-.042.001l-.02.003c-.045.01-.086.03-.119.06l-.343.295-.004.003c-.033.031-.059.069-.073.111l-.296.83-6.119 6.276zm14.768-3.952l.474-.519h1.334l.309.415-1.265 4.107h.493l-.08.209H19.84l1.124-3.564h-2.015l-1.077 3.391h.424l-.073.174h-1.605l1.107-3.548h-2.096l-1.062 3.339h.436l-.072.209H13.27l1.514-4.46H14.198l.091-.271h1.65l.519.537h.906l.491-.554h1.061l.489.535h.953z"/>
|
package/lib/launcher/index.js
CHANGED
|
@@ -27,7 +27,9 @@ const PLUGIN_ID = 'xtralab:launcher';
|
|
|
27
27
|
* The agent list is the merge of xtralab's defaults with the user's
|
|
28
28
|
* `xtralab:launcher` settings, then filtered by a server-side `which`
|
|
29
29
|
* check so users only see agents that are actually installed. Agents with
|
|
30
|
-
* `requireAvailable: false`
|
|
30
|
+
* `requireAvailable: false` skip the filter, as does any built-in whose
|
|
31
|
+
* `command` the user has overridden (a user-chosen command — often a shell
|
|
32
|
+
* alias the server can't resolve — is trusted and always shown).
|
|
31
33
|
*
|
|
32
34
|
* The plugin deliberately does NOT provide the `ILauncher` token: other
|
|
33
35
|
* extensions register notebook/console/terminal cards on it as a side
|
|
@@ -129,7 +131,8 @@ const plugin = {
|
|
|
129
131
|
// the git panel and the stock launcher: let the server resolve
|
|
130
132
|
// the working tree from its root directory.
|
|
131
133
|
repoPath: '',
|
|
132
|
-
cwd: ''
|
|
134
|
+
cwd: '',
|
|
135
|
+
trans
|
|
133
136
|
});
|
|
134
137
|
launcher.title.icon = launcherIcon;
|
|
135
138
|
launcher.title.label = trans.__('Launcher');
|
|
@@ -1,19 +1,4 @@
|
|
|
1
1
|
import type { IAgent } from './agents';
|
|
2
|
-
/**
|
|
3
|
-
* Quote a string so it can be safely passed as a single argument on a
|
|
4
|
-
* bash/zsh command line that is *typed into an interactive terminal* —
|
|
5
|
-
* not the usual file-parsing context.
|
|
6
|
-
*
|
|
7
|
-
* The distinction matters: an actual newline byte (0x0A) sent into a PTY
|
|
8
|
-
* is interpreted by the line discipline as Enter regardless of whether
|
|
9
|
-
* it sits inside `'...'` quotes, so the shell never sees the closing
|
|
10
|
-
* quote. We therefore use ANSI-C `$'...'` quoting and emit `\n` (and
|
|
11
|
-
* `\r`) as their two-character escape sequences; the shell expands them
|
|
12
|
-
* to real newlines after the line is submitted, when readline is no
|
|
13
|
-
* longer involved. Backslashes and single quotes are escaped first so
|
|
14
|
-
* the source text round-trips unchanged.
|
|
15
|
-
*/
|
|
16
|
-
export declare function shellQuote(value: string): string;
|
|
17
2
|
/**
|
|
18
3
|
* Compose the literal command line typed into a fresh terminal for `agent`.
|
|
19
4
|
* When `prompt` is empty (or whitespace-only), this is just `agent.command`.
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* longer involved. Backslashes and single quotes are escaped first so
|
|
13
13
|
* the source text round-trips unchanged.
|
|
14
14
|
*/
|
|
15
|
-
|
|
15
|
+
function shellQuote(value) {
|
|
16
16
|
const escaped = value
|
|
17
17
|
.replace(/\\/g, '\\\\')
|
|
18
18
|
.replace(/'/g, "\\'")
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { ISettingRegistry } from '@jupyterlab/settingregistry';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Schema id the launcher's `agents`/`editors` settings live under.
|
|
4
|
+
*/
|
|
3
5
|
export declare const LAUNCHER_PLUGIN_ID = "xtralab:launcher";
|
|
4
6
|
/**
|
|
5
7
|
* Register a `fetch` transform that injects xtralab's built-in agent and
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { defaultAgentSettings } from './agents';
|
|
2
2
|
import { defaultEditorSettings } from './editors';
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Schema id the launcher's `agents`/`editors` settings live under.
|
|
5
|
+
*/
|
|
4
6
|
export const LAUNCHER_PLUGIN_ID = 'xtralab:launcher';
|
|
5
7
|
/**
|
|
6
8
|
* Setting registries that already have the transform, so both callers skip
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ReadonlyPartialJSONValue } from '@lumino/coreutils';
|
|
2
|
+
/**
|
|
3
|
+
* Parse a JSON-typed value that may have arrived as a string. Agents and the
|
|
4
|
+
* MCP bridge sometimes serialize a spec (e.g. a Vega-Lite object) to a string;
|
|
5
|
+
* for `application/...json` MIME types we accept either and parse the string.
|
|
6
|
+
*/
|
|
7
|
+
export declare function coerceData(mimeType: string, data: ReadonlyPartialJSONValue): ReadonlyPartialJSONValue;
|
package/lib/mimeData.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a JSON-typed value that may have arrived as a string. Agents and the
|
|
3
|
+
* MCP bridge sometimes serialize a spec (e.g. a Vega-Lite object) to a string;
|
|
4
|
+
* for `application/...json` MIME types we accept either and parse the string.
|
|
5
|
+
*/
|
|
6
|
+
export function coerceData(mimeType, data) {
|
|
7
|
+
if (typeof data === 'string' && /\+?json$/.test(mimeType)) {
|
|
8
|
+
try {
|
|
9
|
+
return JSON.parse(data);
|
|
10
|
+
}
|
|
11
|
+
catch (_a) {
|
|
12
|
+
return data;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return data;
|
|
16
|
+
}
|
package/lib/omnibox/index.d.ts
CHANGED
|
@@ -7,6 +7,10 @@ import { IOmnibox } from './tokens';
|
|
|
7
7
|
* it in a fresh terminal through the launcher's `xtralab:start-agent:<id>`
|
|
8
8
|
* commands). It is opened by the top-bar command bar.
|
|
9
9
|
*
|
|
10
|
+
* Commands run and files opened through the overlay are remembered (persisted
|
|
11
|
+
* in the state database) and offered again at the top while the query is
|
|
12
|
+
* empty; the `maxNumberRecents` setting caps how many of each are kept.
|
|
13
|
+
*
|
|
10
14
|
* The agent rows come from the launcher's `IAgentRegistry`; when the launcher
|
|
11
15
|
* is disabled the omnibox still searches files and commands.
|
|
12
16
|
*/
|