xtralab 0.4.0 → 0.6.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.
Files changed (96) hide show
  1. package/README.md +110 -73
  2. package/lib/agentSessions.d.ts +50 -0
  3. package/lib/agentSessions.js +45 -0
  4. package/lib/fileBrowser/index.js +5 -1
  5. package/lib/git/commands.d.ts +12 -13
  6. package/lib/git/commands.js +7 -28
  7. package/lib/git/diffProvider.d.ts +8 -0
  8. package/lib/git/diffProvider.js +314 -0
  9. package/lib/git/diffSurface.d.ts +115 -0
  10. package/lib/git/diffSurface.js +342 -0
  11. package/lib/git/diffWidget.d.ts +8 -13
  12. package/lib/git/diffWidget.js +65 -311
  13. package/lib/git/imageDiff.d.ts +23 -0
  14. package/lib/git/imageDiff.js +256 -0
  15. package/lib/git/index.d.ts +10 -8
  16. package/lib/git/index.js +37 -52
  17. package/lib/index.d.ts +4 -2
  18. package/lib/index.js +14 -8
  19. package/lib/launcher/agents.d.ts +1 -1
  20. package/lib/launcher/agents.js +22 -13
  21. package/lib/launcher/commands.d.ts +32 -6
  22. package/lib/launcher/commands.js +81 -57
  23. package/lib/launcher/dashboard.d.ts +15 -0
  24. package/lib/launcher/dashboard.js +119 -5
  25. package/lib/launcher/editorRegistry.d.ts +43 -0
  26. package/lib/launcher/editorRegistry.js +96 -0
  27. package/lib/launcher/editors.d.ts +78 -0
  28. package/lib/launcher/editors.js +110 -0
  29. package/lib/launcher/icons.d.ts +25 -6
  30. package/lib/launcher/icons.js +116 -19
  31. package/lib/launcher/index.d.ts +2 -22
  32. package/lib/launcher/index.js +48 -25
  33. package/lib/launcher/registry.d.ts +21 -0
  34. package/lib/launcher/registry.js +28 -0
  35. package/lib/launcher/tokens.d.ts +41 -0
  36. package/lib/launcher/tokens.js +17 -0
  37. package/lib/terminals/detection.d.ts +11 -0
  38. package/lib/terminals/detection.js +50 -0
  39. package/lib/terminals/index.d.ts +27 -0
  40. package/lib/terminals/index.js +194 -0
  41. package/lib/terminals/model.d.ts +191 -0
  42. package/lib/terminals/model.js +418 -0
  43. package/lib/terminals/widget.d.ts +72 -0
  44. package/lib/terminals/widget.js +93 -0
  45. package/lib/topBar/icons.d.ts +13 -0
  46. package/lib/topBar/icons.js +27 -0
  47. package/lib/topBar/index.d.ts +16 -0
  48. package/lib/topBar/index.js +86 -0
  49. package/package.json +52 -35
  50. package/schema/launcher.json +56 -1
  51. package/src/agentSessions.ts +94 -0
  52. package/src/fileBrowser/index.ts +5 -1
  53. package/src/git/commands.ts +12 -38
  54. package/src/git/diffProvider.tsx +462 -0
  55. package/src/git/diffSurface.tsx +588 -0
  56. package/src/git/diffWidget.tsx +105 -465
  57. package/src/git/imageDiff.tsx +469 -0
  58. package/src/git/index.ts +38 -68
  59. package/src/index.ts +14 -8
  60. package/src/launcher/agents.ts +23 -14
  61. package/src/launcher/commands.ts +98 -60
  62. package/src/launcher/dashboard.tsx +205 -3
  63. package/src/launcher/editorRegistry.ts +149 -0
  64. package/src/launcher/editors.ts +183 -0
  65. package/src/launcher/icons.ts +120 -20
  66. package/src/launcher/index.ts +62 -27
  67. package/src/launcher/registry.ts +33 -0
  68. package/src/launcher/tokens.ts +51 -0
  69. package/src/terminals/detection.ts +65 -0
  70. package/src/terminals/index.ts +222 -0
  71. package/src/terminals/model.ts +497 -0
  72. package/src/terminals/widget.tsx +240 -0
  73. package/src/topBar/icons.ts +30 -0
  74. package/src/topBar/index.ts +121 -0
  75. package/style/git.css +267 -266
  76. package/style/index.css +2 -1
  77. package/style/index.js +2 -1
  78. package/style/launcher.css +124 -2
  79. package/style/terminals.css +235 -0
  80. package/style/topBar.css +38 -0
  81. package/lib/git/icons.d.ts +0 -14
  82. package/lib/git/icons.js +0 -19
  83. package/lib/git/panel.d.ts +0 -29
  84. package/lib/git/panel.js +0 -42
  85. package/lib/git/panelComponent.d.ts +0 -28
  86. package/lib/git/panelComponent.js +0 -320
  87. package/lib/statusBar/index.d.ts +0 -14
  88. package/lib/statusBar/index.js +0 -89
  89. package/lib/statusBar/widget.d.ts +0 -121
  90. package/lib/statusBar/widget.js +0 -237
  91. package/src/git/icons.ts +0 -20
  92. package/src/git/panel.tsx +0 -56
  93. package/src/git/panelComponent.tsx +0 -575
  94. package/src/statusBar/index.ts +0 -115
  95. package/src/statusBar/widget.tsx +0 -318
  96. package/style/statusBar.css +0 -95
package/README.md CHANGED
@@ -1,9 +1,10 @@
1
1
  # xtralab
2
2
 
3
- An opinionated JupyterLab meta-package.
3
+ An opinionated JupyterLab meta-package for use with coding agents.
4
4
 
5
- Bundles a curated set of extensions, a path-first file browser, a VS Code-style
6
- git changes panel, an agent-focused launcher, and a quieter default workspace.
5
+ It bundles a curated set of JupyterLab extensions, a path-first file browser,
6
+ git diffs rendered by xtralab, an agent launcher, and a quieter default
7
+ workspace.
7
8
 
8
9
  ![xtralab screenshot](./screenshot.png)
9
10
 
@@ -17,7 +18,7 @@ pip install xtralab
17
18
 
18
19
  ### As a JupyterLab package
19
20
 
20
- Run JupyterLab the usual way:
21
+ Once installed, start JupyterLab the usual way:
21
22
 
22
23
  ```bash
23
24
  jupyter lab
@@ -25,81 +26,84 @@ jupyter lab
25
26
 
26
27
  ### As a desktop app
27
28
 
28
- A standalone Electron build (DMG on macOS, AppImage on Linux) ships with each
29
- tagged release — grab the installer for your platform from the
30
- [Releases page](https://github.com/jtpio/xtralab/releases/latest). Builds from
31
- the current `main` branch are also produced on every push as workflow
32
- artifacts under the repository's
29
+ A standalone Electron build is also available, packaged as a DMG on macOS and
30
+ an AppImage on Linux. Each tagged release ships installers on the
31
+ [releases page](https://github.com/jtpio/xtralab/releases/latest), and builds
32
+ from `main` are uploaded as workflow artifacts on the
33
33
  [Actions tab](https://github.com/jtpio/xtralab/actions). See
34
- [CONTRIBUTING.md](./CONTRIBUTING.md) for the architecture and local build
35
- instructions.
34
+ [CONTRIBUTING.md](./CONTRIBUTING.md) for the desktop app architecture and local
35
+ build instructions.
36
36
 
37
37
  ## What's included
38
38
 
39
- - [`ajlab`](https://github.com/jtpio/ajlab) — agent-ready JupyterLab base
40
- - JupyterLab 4.6+
41
- - `jupyterlab-git` — backs the bundled changes panel
42
- - `jupyterlab-lsp` + `ty` — Python LSP via Astral's `ty` (bundled); also
43
- detects `typescript-language-server` on `PATH` for JS/TS
44
- - `jupyterlab-quickopen`
45
- - `jupyterlab-cursor-light`, `jupyterlab-cursor-dark`
46
- - `jupyterlab-day`, `jupyterlab-night` themes
39
+ xtralab builds on [`ajlab`](https://github.com/jtpio/ajlab), the agent-ready
40
+ JupyterLab base. On top of it, xtralab pulls in JupyterLab 4.6+ with
41
+ `jupyterlab-git`, `jupyterlab-lsp`, `jupyterlab-quickopen`, `jupyterlab-vim`,
42
+ and a set of light and dark themes (`jupyterlab-cursor-light`,
43
+ `jupyterlab-cursor-dark`, `jupyterlab-day`, `jupyterlab-night`). See
44
+ [`pyproject.toml`](./pyproject.toml) for the full list and pinned versions.
47
45
 
48
- The bundled labextension adds:
46
+ The bundled xtralab labextension then adds:
49
47
 
50
48
  - A path-first file browser in the left sidebar.
51
- - A "Source Control" panel powered by `jupyterlab-git` and `@pierre/diffs`.
52
- - An agent launcher with a prompt textarea, a row of agent buttons (Claude,
53
- Codex, Gemini, Copilot, Goose, OpenCode, Kiro, Mistral Vibe), and a
54
- collapsible list of changed files. Buttons are filtered to agents installed
55
- on the machine; a typed prompt is shell-quoted and spliced into the launch
56
- command for agents that accept one.
49
+ - Git diffs rendered by xtralab in the `jupyterlab-git` panel, using
50
+ `@pierre/diffs` for text and notebooks and a 2-up / swipe / onion-skin view
51
+ for images.
52
+ - An agent launcher with a prompt box, buttons for the agents installed on your
53
+ machine (Claude, Codex, Antigravity, Copilot, Goose, OpenCode, Kiro, Mistral
54
+ Vibe), a collapsible list of changed files, and an Open row for a terminal,
55
+ notebook, console, or your terminal editor (Neovim or Vim).
56
+ - A Terminals panel listing the running terminal sessions, each badged with the
57
+ agent or editor detected inside it. Open terminal tabs in the main area carry
58
+ the same icon.
59
+ - Sidebar toggle buttons in the top bar for the left and right areas.
60
+
61
+ ## Connecting agents to Jupyter (MCP)
62
+
63
+ xtralab runs a [Model Context Protocol][mcp-spec] server inside JupyterLab,
64
+ provided by [`jupyter-server-mcp`][mcp]. To let a coding agent drive JupyterLab
65
+ through it, register the bundled `jupyter-server-mcp-proxy` console script with
66
+ the agent:
57
67
 
58
- ## Language servers
59
-
60
- xtralab ships with
61
- [`jupyterlab-lsp`](https://github.com/jupyter-lsp/jupyterlab-lsp) and
62
- pre-registers two language servers through
63
- `jupyter_server_config.d/xtralab-lsp.json`:
68
+ ```bash
69
+ claude mcp add jupyter -- jupyter-server-mcp-proxy
70
+ codex mcp add jupyter -- jupyter-server-mcp-proxy
71
+ copilot mcp add jupyter -- jupyter-server-mcp-proxy
72
+ ```
64
73
 
65
- - **Python — [`ty`](https://github.com/astral-sh/ty)** — installed as a
66
- Python dependency. Works out of the box.
67
- - **TypeScript / JavaScript — `typescript-language-server`** — install
68
- yourself:
74
+ Run this from a terminal inside xtralab, so the proxy inherits the server
75
+ environment and discovers the running server automatically. No port is needed,
76
+ and a single registration keeps working across restarts. The launcher also
77
+ surfaces these commands with copy buttons, filtered to the agents you have
78
+ installed.
69
79
 
70
- ```bash
71
- npm install -g typescript-language-server typescript
72
- ```
80
+ See the [`jupyter-server-mcp` README][mcp] for other MCP clients.
73
81
 
74
- Restart JupyterLab (or the desktop app) after installing.
82
+ [mcp]: https://github.com/jupyter-ai-contrib/jupyter-server-mcp
83
+ [mcp-spec]: https://modelcontextprotocol.io
75
84
 
76
- Specs use bare command names (`["ty", "server"]`), so binaries are resolved
77
- from `PATH` at spawn time.
78
-
79
- ### Where binaries are discovered
85
+ ## Language servers
80
86
 
81
- - **`pip install xtralab`** — anything on the JupyterLab process's `PATH`.
82
- - **Desktop app** — the supervisor augments `PATH` with common shim
83
- locations (`~/.volta/bin`, `~/.npm-global/bin`, `~/.bun/bin`,
84
- `~/.asdf/shims`, `~/.mise/shims`, `/opt/homebrew/bin`, `/usr/local/bin`,
85
- …). Set `XTRALAB_EXTRA_PATH` (colon-separated) before launching the app
86
- to add directories the defaults miss.
87
+ xtralab ships [`jupyterlab-lsp`][lsp] with two language servers pre-registered:
87
88
 
88
- ### Adding more servers
89
+ - Python, using [`ty`](https://github.com/astral-sh/ty), which is bundled and
90
+ works out of the box.
91
+ - TypeScript and JavaScript, using `typescript-language-server`, which you
92
+ install yourself:
89
93
 
90
- To enable another server (bash, yaml, json, dockerfile, pyright, …),
91
- install the binary then drop a JSON file into a `jupyter_server_config.d/`
92
- directory:
94
+ ```bash
95
+ npm install -g typescript-language-server typescript
96
+ ```
93
97
 
94
- - **`pip install xtralab`** — run `jupyter --paths` and pick a config dir
95
- (typically `~/.jupyter/jupyter_server_config.d/`).
96
- - **Desktop app (macOS)** —
97
- `~/Library/Application Support/xtralab/jupyter/config/jupyter_server_config.d/`
98
- (or `xtralab dev` for local dev builds).
99
- - **Desktop app (Linux AppImage)** —
100
- `~/.config/xtralab/jupyter/config/jupyter_server_config.d/`.
98
+ Restart JupyterLab afterwards to pick it up.
101
99
 
102
- Example (`bash-lsp.json`):
100
+ To enable another server (bash, yaml, json, pyright, and more), install its
101
+ binary and drop a JSON spec into a `jupyter_server_config.d/` directory. For
102
+ `pip install xtralab`, run `jupyter --paths` to find one (typically
103
+ `~/.jupyter/jupyter_server_config.d/`). For the desktop app, use
104
+ `~/Library/Application Support/xtralab/jupyter/config/jupyter_server_config.d/`
105
+ on macOS or `~/.config/xtralab/jupyter/config/jupyter_server_config.d/` on
106
+ Linux.
103
107
 
104
108
  ```json
105
109
  {
@@ -117,15 +121,19 @@ Example (`bash-lsp.json`):
117
121
  }
118
122
  ```
119
123
 
120
- Pair with `npm install -g bash-language-server`. Reuse a bundled `key` to
121
- override it. See
122
- [jupyterlab-lsp's docs](https://jupyterlab-lsp.readthedocs.io/en/latest/Configuring.html)
123
- for the full spec schema.
124
+ See the [`jupyterlab-lsp` documentation][lsp-config] for the full spec.
125
+
126
+ [lsp]: https://github.com/jupyter-lsp/jupyterlab-lsp
127
+ [lsp-config]: https://jupyterlab-lsp.readthedocs.io/en/latest/Configuring.html
124
128
 
125
129
  ## Customizing the launcher
126
130
 
127
- Open `Settings → Settings Editor → xtralab launcher` and edit the `agents`
128
- array. Entries are merged with the defaults by `id`.
131
+ Open `Settings → Settings Editor → xtralab launcher` to override, hide, or add
132
+ launcher entries. Both lists below merge with xtralab's defaults by `id`.
133
+
134
+ ### Agents
135
+
136
+ Edit the `agents` array:
129
137
 
130
138
  ```jsonc
131
139
  {
@@ -142,14 +150,43 @@ array. Entries are merged with the defaults by `id`.
142
150
  }
143
151
  ```
144
152
 
145
- Fields: `id` (required), `label`, `caption`, `command`, `promptArgs` (how to
146
- splice the prompt — `[]` for positional, `["--flag"]` for flagged, `null` to
147
- opt out), `iconSvg`, `rank`, `enabled`, `requireAvailable`.
153
+ Fields: `id` (required), `label`, `caption`, `command`, `promptArgs` (how the
154
+ prompt is spliced: `[]` for positional, `["--flag"]` for flagged, `null` to opt
155
+ out), `iconSvg`, `rank`, `enabled`, `requireAvailable`.
156
+
157
+ ### Editors
158
+
159
+ The **Open** section's terminal-editor tile (Neovim, falling back to Vim) is
160
+ configured the same way through an `editors` array:
161
+
162
+ ```jsonc
163
+ {
164
+ "editors": [
165
+ // Hide Neovim so the tile falls back to Vim (or disappears if Vim
166
+ // isn't installed either)
167
+ { "id": "nvim", "enabled": false },
168
+
169
+ // Add Helix, preferred over the built-ins
170
+ {
171
+ "id": "helix",
172
+ "label": "Helix",
173
+ "command": "hx",
174
+ "rank": -1,
175
+ "iconSvg": "<svg>…</svg>"
176
+ }
177
+ ]
178
+ }
179
+ ```
180
+
181
+ The launcher shows a single tile: the first editor, by `rank`, whose `command`
182
+ is on `PATH`. Disable both built-ins (`nvim`, `vim`) to remove the tile
183
+ entirely. Fields: `id` (required), `label`, `caption`, `command`, `iconSvg`,
184
+ `rank`, `enabled`, `requireAvailable`.
148
185
 
149
186
  ## Contributing
150
187
 
151
- See [CONTRIBUTING.md](./CONTRIBUTING.md) for the development setup, the
152
- Electron desktop app architecture, and the build pipeline.
188
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for the development setup, the Electron
189
+ desktop app architecture, and the build pipeline.
153
190
 
154
191
  ## License
155
192
 
@@ -0,0 +1,50 @@
1
+ import type { JupyterFrontEndPlugin } from '@jupyterlab/application';
2
+ import { Token } from '@lumino/coreutils';
3
+ import { ISignal } from '@lumino/signaling';
4
+ /**
5
+ * A shared map from a terminal session name to the agent command it was
6
+ * *launched* with (e.g. `claude`).
7
+ *
8
+ * This is the optimistic half of the running-agent badge: when the launcher
9
+ * (or the terminals panel's `+` menu) starts an agent via a
10
+ * `xtralab:start-agent:<id>` command, it records the session here so the
11
+ * panel can show the agent's logo immediately, before the server-side
12
+ * process detection has had a chance to confirm it. Server detection is the
13
+ * authoritative source once it reports on a session; this tag only fills the
14
+ * gap right after launch (and serves as a fallback if detection is
15
+ * unavailable).
16
+ *
17
+ * It exists as its own token, provided by a tiny dependency-free plugin,
18
+ * specifically so the launcher (the writer) and the terminals panel (the
19
+ * reader) can share it without depending on each other — a direct
20
+ * launcher↔terminals token pair would form an activation cycle.
21
+ */
22
+ export interface IAgentSessions {
23
+ /**
24
+ * The agent command a session was launched with, or `null` if we never
25
+ * launched an agent into it (e.g. a plain terminal, or one started before
26
+ * this ran).
27
+ */
28
+ get(sessionName: string): string | null;
29
+ /** Record that a session was launched as the given agent command. */
30
+ set(sessionName: string, command: string): void;
31
+ /** Forget a session — called when it shuts down so the map stays bounded. */
32
+ delete(sessionName: string): void;
33
+ /**
34
+ * Emitted with the affected session name whenever a record is added or
35
+ * removed, so readers can re-render.
36
+ */
37
+ readonly changed: ISignal<IAgentSessions, string>;
38
+ }
39
+ /**
40
+ * DI token for {@link IAgentSessions}. Provided by `xtralab:agent-sessions`;
41
+ * consumed (optionally) by both `xtralab:launcher` and `xtralab:terminals`.
42
+ */
43
+ export declare const IAgentSessions: Token<IAgentSessions>;
44
+ /**
45
+ * Provides {@link IAgentSessions}. Deliberately has no dependencies so it can
46
+ * sit underneath both the launcher and the terminals panel without creating
47
+ * a dependency cycle between them.
48
+ */
49
+ declare const plugin: JupyterFrontEndPlugin<IAgentSessions>;
50
+ export default plugin;
@@ -0,0 +1,45 @@
1
+ import { Token } from '@lumino/coreutils';
2
+ import { Signal } from '@lumino/signaling';
3
+ /**
4
+ * DI token for {@link IAgentSessions}. Provided by `xtralab:agent-sessions`;
5
+ * consumed (optionally) by both `xtralab:launcher` and `xtralab:terminals`.
6
+ */
7
+ export const IAgentSessions = new Token('xtralab:IAgentSessions', 'A shared map from terminal session name to the agent command it was launched with.');
8
+ class AgentSessions {
9
+ constructor() {
10
+ this._byName = new Map();
11
+ this._changed = new Signal(this);
12
+ }
13
+ get(sessionName) {
14
+ var _a;
15
+ return (_a = this._byName.get(sessionName)) !== null && _a !== void 0 ? _a : null;
16
+ }
17
+ set(sessionName, command) {
18
+ if (this._byName.get(sessionName) === command) {
19
+ return;
20
+ }
21
+ this._byName.set(sessionName, command);
22
+ this._changed.emit(sessionName);
23
+ }
24
+ delete(sessionName) {
25
+ if (this._byName.delete(sessionName)) {
26
+ this._changed.emit(sessionName);
27
+ }
28
+ }
29
+ get changed() {
30
+ return this._changed;
31
+ }
32
+ }
33
+ /**
34
+ * Provides {@link IAgentSessions}. Deliberately has no dependencies so it can
35
+ * sit underneath both the launcher and the terminals panel without creating
36
+ * a dependency cycle between them.
37
+ */
38
+ const plugin = {
39
+ id: 'xtralab:agent-sessions',
40
+ description: 'Shared map from terminal session to the agent command it was launched with, used to badge terminal rows with the running agent.',
41
+ autoStart: true,
42
+ provides: IAgentSessions,
43
+ activate: () => new AgentSessions()
44
+ };
45
+ export default plugin;
@@ -22,7 +22,11 @@ const plugin = {
22
22
  void app.commands.execute('docmanager:open', { path: serverPath });
23
23
  }
24
24
  });
25
- app.shell.add(browser, 'left', { rank: 50 });
25
+ // Ranks just under the Terminals panel in the left sidebar. The shipped
26
+ // `layout` setting assigns the default ranks (rank only, no area pin),
27
+ // so this browser stays movable via the "Move Widget" context menu; the
28
+ // `rank` here is the in-code fallback for when that setting is absent.
29
+ app.shell.add(browser, 'left', { rank: 2 });
26
30
  if (restorer) {
27
31
  restorer.add(browser, browser.id);
28
32
  }
@@ -1,17 +1,16 @@
1
1
  import { JupyterFrontEnd } from '@jupyterlab/application';
2
- import { ICommandPalette, IThemeManager } from '@jupyterlab/apputils';
2
+ import { IThemeManager } from '@jupyterlab/apputils';
3
3
  import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
4
4
  import { Contents } from '@jupyterlab/services';
5
5
  import { createGitDiffWidget, diffWidgetId } from './diffWidget';
6
- import { GitPanel } from './panel';
7
6
  import { IFileChange } from './tokens';
8
7
  /**
9
- * Command IDs exposed by the git plugin. Both are registered in
10
- * {@link registerGitCommands} so other extensions, the command palette and
11
- * keybindings can drive the panel without going through the React internals.
8
+ * Command IDs exposed by the launcher's git diff path. The launcher
9
+ * dashboard's "Changes" section drives {@link CommandIDs.openDiff} to open
10
+ * its own diff tab, independent of `jupyterlab-git` (whose panel reaches
11
+ * the same rendering via the providers in `diffProvider.tsx`).
12
12
  */
13
13
  export declare namespace CommandIDs {
14
- const refresh = "xtralab:git:refresh";
15
14
  const openDiff = "xtralab:git:open-diff";
16
15
  }
17
16
  /**
@@ -29,9 +28,7 @@ export declare namespace CommandArguments {
29
28
  }
30
29
  export interface IRegisterGitCommandsOptions {
31
30
  app: JupyterFrontEnd;
32
- panel: GitPanel;
33
31
  themeManager: IThemeManager | null;
34
- commandPalette: ICommandPalette | null;
35
32
  /**
36
33
  * Contents manager used by the diff widget to write hunk-discard
37
34
  * results back to the working tree.
@@ -46,7 +43,10 @@ export interface IRegisterGitCommandsOptions {
46
43
  rendermime: IRenderMimeRegistry | null;
47
44
  /**
48
45
  * Called whenever the diff widget mutates the working tree (e.g. after
49
- * a hunk discard) so the plugin can refresh the changes panel.
46
+ * a hunk discard). The launcher dashboard polls git status on its own
47
+ * cadence and `jupyterlab-git`'s panel auto-refreshes on the contents
48
+ * `fileChanged` signal the save emits, so this is a hook for any extra
49
+ * bookkeeping rather than a required refresh.
50
50
  */
51
51
  onChanged: () => void;
52
52
  /**
@@ -63,9 +63,8 @@ export interface IRegisterGitCommandsOptions {
63
63
  onPinned(widget: ReturnType<typeof createGitDiffWidget>): void;
64
64
  }
65
65
  /**
66
- * Register the git commands on the application command registry. Returns
67
- * a disposer that clears the command palette items the registration created
68
- * (the commands themselves stay registered for the lifetime of the plugin).
66
+ * Register the launcher's git diff command on the application command
67
+ * registry.
69
68
  */
70
- export declare function registerGitCommands(options: IRegisterGitCommandsOptions): () => void;
69
+ export declare function registerGitCommands(options: IRegisterGitCommandsOptions): void;
71
70
  export { diffWidgetId };
@@ -1,31 +1,21 @@
1
- import { refreshIcon } from '@jupyterlab/ui-components';
2
1
  import { createGitDiffWidget, diffWidgetId, updateGitDiffWidget } from './diffWidget';
3
2
  /**
4
- * Command IDs exposed by the git plugin. Both are registered in
5
- * {@link registerGitCommands} so other extensions, the command palette and
6
- * keybindings can drive the panel without going through the React internals.
3
+ * Command IDs exposed by the launcher's git diff path. The launcher
4
+ * dashboard's "Changes" section drives {@link CommandIDs.openDiff} to open
5
+ * its own diff tab, independent of `jupyterlab-git` (whose panel reaches
6
+ * the same rendering via the providers in `diffProvider.tsx`).
7
7
  */
8
8
  export var CommandIDs;
9
9
  (function (CommandIDs) {
10
- CommandIDs.refresh = 'xtralab:git:refresh';
11
10
  CommandIDs.openDiff = 'xtralab:git:open-diff';
12
11
  })(CommandIDs || (CommandIDs = {}));
13
12
  /**
14
- * Register the git commands on the application command registry. Returns
15
- * a disposer that clears the command palette items the registration created
16
- * (the commands themselves stay registered for the lifetime of the plugin).
13
+ * Register the launcher's git diff command on the application command
14
+ * registry.
17
15
  */
18
16
  export function registerGitCommands(options) {
19
- const { app, panel, themeManager, commandPalette, contentsManager, rendermime, onChanged, trackDiff, findDiff, onPinned } = options;
17
+ const { app, themeManager, contentsManager, rendermime, onChanged, trackDiff, findDiff, onPinned } = options;
20
18
  const { commands } = app;
21
- commands.addCommand(CommandIDs.refresh, {
22
- label: 'Refresh Git Changes',
23
- caption: 'Refresh the git changes panel',
24
- icon: refreshIcon,
25
- execute: () => {
26
- panel.refresh();
27
- }
28
- });
29
19
  commands.addCommand(CommandIDs.openDiff, {
30
20
  label: 'Open Git Diff',
31
21
  caption: 'Open a side-by-side diff for a changed file',
@@ -58,16 +48,5 @@ export function registerGitCommands(options) {
58
48
  app.shell.activateById(widget.id);
59
49
  }
60
50
  });
61
- const paletteItems = commandPalette
62
- ? [
63
- commandPalette.addItem({
64
- command: CommandIDs.refresh,
65
- category: 'Git'
66
- })
67
- ]
68
- : [];
69
- return () => {
70
- paletteItems.forEach(item => item.dispose());
71
- };
72
51
  }
73
52
  export { diffWidgetId };
@@ -0,0 +1,8 @@
1
+ import { JupyterFrontEndPlugin } from '@jupyterlab/application';
2
+ /**
3
+ * Registers xtralab's diff rendering as jupyterlab-git's diff providers:
4
+ * `@pierre/diffs` for text and notebooks, the bundled `<img>`-based view
5
+ * for raster images.
6
+ */
7
+ declare const diffProviderPlugin: JupyterFrontEndPlugin<void>;
8
+ export default diffProviderPlugin;