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.
Files changed (237) hide show
  1. package/README.md +65 -30
  2. package/lib/about/icons.d.ts +0 -5
  3. package/lib/about/icons.js +0 -5
  4. package/lib/about/index.d.ts +4 -8
  5. package/lib/about/index.js +6 -17
  6. package/lib/agentSessions.d.ts +9 -29
  7. package/lib/agentSessions.js +2 -7
  8. package/lib/askAgent/editorSelection.d.ts +20 -26
  9. package/lib/askAgent/editorSelection.js +11 -26
  10. package/lib/askAgent/icons.d.ts +2 -3
  11. package/lib/askAgent/icons.js +2 -3
  12. package/lib/askAgent/index.d.ts +4 -26
  13. package/lib/askAgent/index.js +54 -158
  14. package/lib/askAgent/popup.d.ts +12 -16
  15. package/lib/askAgent/popup.js +18 -37
  16. package/lib/askAgent/prompt.d.ts +3 -5
  17. package/lib/askAgent/prompt.js +6 -19
  18. package/lib/askAgent/queue.d.ts +11 -21
  19. package/lib/askAgent/queue.js +9 -19
  20. package/lib/askAgent/queuePanel.d.ts +13 -18
  21. package/lib/askAgent/queuePanel.js +15 -37
  22. package/lib/askAgent/targetPicker.d.ts +2 -9
  23. package/lib/askAgent/targetPicker.js +6 -11
  24. package/lib/askAgent/tokens.d.ts +32 -46
  25. package/lib/askAgent/tokens.js +4 -6
  26. package/lib/commandBar/index.d.ts +4 -13
  27. package/lib/commandBar/index.js +21 -39
  28. package/lib/customPanel/index.js +15 -0
  29. package/lib/editorBreadcrumbs/index.d.ts +3 -6
  30. package/lib/editorBreadcrumbs/index.js +10 -6
  31. package/lib/editorBreadcrumbs/widget.d.ts +17 -4
  32. package/lib/editorBreadcrumbs/widget.js +11 -17
  33. package/lib/editorIndent/index.d.ts +4 -12
  34. package/lib/editorIndent/index.js +8 -23
  35. package/lib/fileBrowser/commands.d.ts +29 -19
  36. package/lib/fileBrowser/commands.js +83 -97
  37. package/lib/fileBrowser/contents.d.ts +3 -0
  38. package/lib/fileBrowser/dragAndDrop.d.ts +17 -4
  39. package/lib/fileBrowser/dragAndDrop.js +2 -7
  40. package/lib/fileBrowser/fileBrowser.d.ts +19 -9
  41. package/lib/fileBrowser/fileBrowser.js +70 -222
  42. package/lib/fileBrowser/gitStatus.d.ts +16 -10
  43. package/lib/fileBrowser/gitStatus.js +31 -30
  44. package/lib/fileBrowser/gitignore.d.ts +4 -17
  45. package/lib/fileBrowser/gitignore.js +4 -25
  46. package/lib/fileBrowser/icons.d.ts +7 -17
  47. package/lib/fileBrowser/icons.js +25 -80
  48. package/lib/fileBrowser/index.js +2 -4
  49. package/lib/fileBrowser/widget.d.ts +141 -48
  50. package/lib/fileBrowser/widget.js +102 -4
  51. package/lib/fileTypeIcons/index.js +0 -10
  52. package/lib/git/api.d.ts +5 -13
  53. package/lib/git/api.js +10 -36
  54. package/lib/git/askRequest.d.ts +4 -8
  55. package/lib/git/askRequest.js +6 -20
  56. package/lib/git/commands.d.ts +45 -5
  57. package/lib/git/commands.js +20 -13
  58. package/lib/git/diffModel.js +4 -0
  59. package/lib/git/diffPreferences.d.ts +90 -0
  60. package/lib/git/diffPreferences.js +107 -0
  61. package/lib/git/diffProvider.js +10 -2
  62. package/lib/git/diffSurface.d.ts +64 -63
  63. package/lib/git/diffSurface.js +72 -213
  64. package/lib/git/diffTheme.d.ts +7 -0
  65. package/lib/git/diffTheme.js +23 -0
  66. package/lib/git/diffWidget.d.ts +70 -14
  67. package/lib/git/diffWidget.js +100 -94
  68. package/lib/git/imageDiff.d.ts +14 -6
  69. package/lib/git/imageDiff.js +19 -75
  70. package/lib/git/index.d.ts +0 -3
  71. package/lib/git/index.js +44 -10
  72. package/lib/git/notebookDiff.d.ts +110 -33
  73. package/lib/git/notebookDiff.js +55 -197
  74. package/lib/git/tokens.d.ts +73 -31
  75. package/lib/git/tokens.js +2 -3
  76. package/lib/highlight/index.d.ts +4 -10
  77. package/lib/highlight/index.js +10 -41
  78. package/lib/index.d.ts +0 -9
  79. package/lib/index.js +0 -9
  80. package/lib/launcher/agents.d.ts +55 -51
  81. package/lib/launcher/agents.js +15 -57
  82. package/lib/launcher/availability.d.ts +3 -9
  83. package/lib/launcher/availability.js +3 -9
  84. package/lib/launcher/commands.d.ts +7 -32
  85. package/lib/launcher/commands.js +14 -45
  86. package/lib/launcher/dashboard.d.ts +19 -24
  87. package/lib/launcher/dashboard.js +21 -67
  88. package/lib/launcher/editorRegistry.d.ts +10 -22
  89. package/lib/launcher/editorRegistry.js +14 -18
  90. package/lib/launcher/editors.d.ts +39 -45
  91. package/lib/launcher/editors.js +8 -34
  92. package/lib/launcher/icons.d.ts +0 -12
  93. package/lib/launcher/icons.js +5 -39
  94. package/lib/launcher/index.js +12 -55
  95. package/lib/launcher/invocation.d.ts +4 -10
  96. package/lib/launcher/invocation.js +7 -22
  97. package/lib/launcher/registry.d.ts +9 -7
  98. package/lib/launcher/registry.js +9 -7
  99. package/lib/launcher/tokens.d.ts +10 -22
  100. package/lib/launcher/tokens.js +5 -8
  101. package/lib/menuBar/index.d.ts +3 -10
  102. package/lib/menuBar/index.js +11 -28
  103. package/lib/menus/index.d.ts +3 -9
  104. package/lib/menus/index.js +14 -30
  105. package/lib/omnibox/files.d.ts +2 -4
  106. package/lib/omnibox/files.js +5 -11
  107. package/lib/omnibox/index.d.ts +4 -14
  108. package/lib/omnibox/index.js +9 -27
  109. package/lib/omnibox/model.d.ts +38 -10
  110. package/lib/omnibox/model.js +15 -33
  111. package/lib/omnibox/recents.d.ts +15 -17
  112. package/lib/omnibox/recents.js +12 -17
  113. package/lib/omnibox/tokens.d.ts +5 -10
  114. package/lib/omnibox/tokens.js +2 -6
  115. package/lib/omnibox/widget.d.ts +11 -7
  116. package/lib/omnibox/widget.js +8 -16
  117. package/lib/searchReplace/index.d.ts +4 -20
  118. package/lib/searchReplace/index.js +7 -27
  119. package/lib/showOutput/index.d.ts +3 -12
  120. package/lib/showOutput/index.js +6 -22
  121. package/lib/sidebar/index.d.ts +4 -7
  122. package/lib/sidebar/index.js +5 -12
  123. package/lib/terminalNotifications/index.d.ts +4 -10
  124. package/lib/terminalNotifications/index.js +6 -20
  125. package/lib/terminals/agentTerminals.d.ts +12 -5
  126. package/lib/terminals/agentTerminals.js +25 -44
  127. package/lib/terminals/detection.d.ts +4 -8
  128. package/lib/terminals/detection.js +4 -8
  129. package/lib/terminals/index.d.ts +0 -35
  130. package/lib/terminals/index.js +12 -101
  131. package/lib/terminals/model.d.ts +64 -139
  132. package/lib/terminals/model.js +80 -220
  133. package/lib/terminals/tokens.d.ts +11 -22
  134. package/lib/terminals/tokens.js +2 -2
  135. package/lib/terminals/widget.d.ts +43 -13
  136. package/lib/terminals/widget.js +33 -18
  137. package/lib/topBar/icons.d.ts +3 -8
  138. package/lib/topBar/icons.js +3 -8
  139. package/lib/topBar/index.d.ts +4 -11
  140. package/lib/topBar/index.js +10 -38
  141. package/lib/walkthrough/index.d.ts +4 -9
  142. package/lib/walkthrough/index.js +6 -20
  143. package/lib/walkthrough/panel.d.ts +40 -9
  144. package/lib/walkthrough/panel.js +4 -10
  145. package/package.json +5 -3
  146. package/schema/git-diff-preferences.json +42 -0
  147. package/src/about/icons.ts +0 -5
  148. package/src/about/index.tsx +6 -17
  149. package/src/agentSessions.ts +9 -29
  150. package/src/askAgent/editorSelection.ts +22 -29
  151. package/src/askAgent/icons.ts +2 -3
  152. package/src/askAgent/index.ts +54 -158
  153. package/src/askAgent/popup.tsx +23 -45
  154. package/src/askAgent/prompt.ts +6 -19
  155. package/src/askAgent/queue.ts +13 -24
  156. package/src/askAgent/queuePanel.tsx +21 -46
  157. package/src/askAgent/targetPicker.tsx +5 -15
  158. package/src/askAgent/tokens.ts +32 -46
  159. package/src/commandBar/index.ts +24 -39
  160. package/src/customPanel/index.ts +15 -0
  161. package/src/editorBreadcrumbs/index.ts +10 -6
  162. package/src/editorBreadcrumbs/widget.ts +23 -17
  163. package/src/editorIndent/index.ts +17 -23
  164. package/src/fileBrowser/commands.ts +119 -96
  165. package/src/fileBrowser/contents.ts +3 -0
  166. package/src/fileBrowser/dragAndDrop.ts +17 -7
  167. package/src/fileBrowser/fileBrowser.tsx +86 -230
  168. package/src/fileBrowser/gitStatus.ts +36 -33
  169. package/src/fileBrowser/gitignore.ts +4 -25
  170. package/src/fileBrowser/icons.ts +25 -80
  171. package/src/fileBrowser/index.ts +2 -4
  172. package/src/fileBrowser/widget.tsx +171 -50
  173. package/src/fileTypeIcons/index.ts +0 -10
  174. package/src/git/api.ts +10 -36
  175. package/src/git/askRequest.ts +6 -20
  176. package/src/git/commands.ts +83 -11
  177. package/src/git/diffModel.ts +25 -0
  178. package/src/git/diffPreferences.ts +192 -0
  179. package/src/git/diffProvider.tsx +11 -2
  180. package/src/git/diffSurface.tsx +165 -286
  181. package/src/git/diffTheme.ts +24 -0
  182. package/src/git/diffWidget.tsx +194 -134
  183. package/src/git/imageDiff.tsx +56 -84
  184. package/src/git/index.ts +54 -10
  185. package/src/git/notebookDiff.tsx +214 -240
  186. package/src/git/tokens.ts +73 -31
  187. package/src/highlight/index.ts +10 -41
  188. package/src/index.ts +0 -9
  189. package/src/launcher/agents.ts +64 -95
  190. package/src/launcher/availability.ts +3 -9
  191. package/src/launcher/commands.ts +14 -51
  192. package/src/launcher/dashboard.tsx +49 -88
  193. package/src/launcher/editorRegistry.ts +21 -29
  194. package/src/launcher/editors.ts +39 -58
  195. package/src/launcher/icons.ts +5 -39
  196. package/src/launcher/index.ts +12 -55
  197. package/src/launcher/invocation.ts +7 -22
  198. package/src/launcher/registry.ts +9 -7
  199. package/src/launcher/tokens.ts +10 -22
  200. package/src/menuBar/index.ts +11 -28
  201. package/src/menus/index.ts +14 -30
  202. package/src/omnibox/files.ts +10 -14
  203. package/src/omnibox/index.ts +9 -27
  204. package/src/omnibox/model.ts +50 -38
  205. package/src/omnibox/recents.ts +17 -22
  206. package/src/omnibox/tokens.ts +5 -10
  207. package/src/omnibox/widget.tsx +14 -19
  208. package/src/searchReplace/index.ts +7 -27
  209. package/src/showOutput/index.ts +6 -22
  210. package/src/sidebar/index.ts +20 -12
  211. package/src/terminalNotifications/index.ts +42 -25
  212. package/src/terminals/agentTerminals.ts +25 -49
  213. package/src/terminals/detection.ts +4 -8
  214. package/src/terminals/index.ts +12 -101
  215. package/src/terminals/model.ts +130 -246
  216. package/src/terminals/tokens.ts +11 -22
  217. package/src/terminals/widget.tsx +48 -31
  218. package/src/topBar/icons.ts +3 -8
  219. package/src/topBar/index.ts +21 -44
  220. package/src/walkthrough/index.ts +6 -20
  221. package/src/walkthrough/panel.ts +40 -10
  222. package/style/about.css +2 -7
  223. package/style/askAgent.css +8 -40
  224. package/style/base.css +9 -45
  225. package/style/chrome.css +108 -308
  226. package/style/commandBar.css +4 -20
  227. package/style/customPanel.css +1 -4
  228. package/style/git.css +26 -186
  229. package/style/highlight.css +1 -3
  230. package/style/launcher.css +6 -70
  231. package/style/omnibox.css +2 -14
  232. package/style/showOutput.css +0 -6
  233. package/style/sidebar.css +29 -9
  234. package/style/tabs.css +5 -13
  235. package/style/terminals.css +6 -53
  236. package/style/topBar.css +2 -22
  237. package/style/walkthrough.css +0 -8
@@ -23,41 +23,6 @@ import { RunningTerminals } from './widget';
23
23
 
24
24
  const PLUGIN_ID = 'xtralab:terminals';
25
25
 
26
- /**
27
- * Adds a left-sidebar panel that lists every running terminal session.
28
- *
29
- * Each row is labelled with the *real* title the running program
30
- * published — the launcher's agent name, or whatever title an xterm
31
- * escape sequence set — which the registry caches so it survives the
32
- * user closing the tab while the session keeps running on the server.
33
- * JupyterLab's built-in "Running Terminals and Kernels" panel lists the
34
- * same sessions but only by their `terminals/<n>` name, so this panel
35
- * resolves and caches the published title to show something meaningful.
36
- * Rows running a coding agent carry a smaller second line below the
37
- * title with the agent's latest line of output, so the panel shows what
38
- * each agent is doing at a glance — on by default, and switchable off
39
- * through the `showAgentActivity` setting.
40
- *
41
- * Clicking a row activates the existing tab if one is open, or reopens
42
- * the session in a fresh terminal widget (`terminal:open`). The inline
43
- * `×` button shuts the session down on the server. The Terminals
44
- * section's title toolbar carries a `+` button and a stop button (the
45
- * latter shuts every session down at once, after a confirmation).
46
- *
47
- * The list is one movable section, and other panels' sections can move in.
48
- *
49
- * The `+` button drops down a menu — built from the launcher's shared
50
- * `IAgentRegistry` — listing each available agent (Claude, Codex, …)
51
- * followed by a plain terminal, so starting an agent session is as
52
- * consistent here as in the launcher and reuses the very same registered
53
- * commands and icons. When the launcher is disabled or no agents are
54
- * installed, the button falls back to opening a plain terminal directly.
55
- *
56
- * The plugin also provides {@link IAgentTerminals} — the sessions with a
57
- * detection-confirmed running agent, plus a "paste a prompt into one"
58
- * action — which the ask-agent popup uses to offer running agents as
59
- * targets next to "new terminal".
60
- */
61
26
  const plugin: JupyterFrontEndPlugin<IAgentTerminals> = {
62
27
  id: PLUGIN_ID,
63
28
  description:
@@ -87,13 +52,8 @@ const plugin: JupyterFrontEndPlugin<IAgentTerminals> = {
87
52
  ): IAgentTerminals => {
88
53
  const trans = (translator ?? nullTranslator).load('jupyterlab');
89
54
 
90
- // Resolve a running agent/editor identifier to an icon: the matching
91
- // agent's logo, the matching editor's logo (Neovim/Vim), or the plain
92
- // terminal icon when nothing recognised is running. Detection reports
93
- // either the configured `command` or the canonical `id` (see
94
- // `detectCommands`), so a row whose command is an alias — e.g. `ccm` for
95
- // `claude` — still resolves to the right logo via its id. Reads the
96
- // registries live so it tracks settings changes. Used to badge each row.
55
+ // Detection reports either the configured `command` or the canonical `id`,
56
+ // so an aliased command (e.g. `ccm` for `claude`) still maps to its logo.
97
57
  const iconForCommand = (command: string | null): LabIcon => {
98
58
  if (!command) {
99
59
  return terminalIcon;
@@ -104,21 +64,12 @@ const plugin: JupyterFrontEndPlugin<IAgentTerminals> = {
104
64
  if (agent) {
105
65
  return agent.icon;
106
66
  }
107
- // A terminal running an editor (Neovim/Vim, or a user-configured one) is
108
- // badged with its logo, the same as an agent.
109
67
  const editor = editorRegistry?.editors.find(
110
68
  e => e.command === command || e.id === command
111
69
  );
112
70
  return editor?.icon ?? terminalIcon;
113
71
  };
114
72
 
115
- // The names the server should look for in each terminal's process tree:
116
- // for every agent and editor, its configured `command` plus its canonical
117
- // `id`. The id is the real CLI name (e.g. `claude`, `nvim`), so an agent
118
- // whose command points at an alias — e.g. `ccm` running `claude` — is
119
- // still recognised by the process it actually spawns. Read live so the
120
- // list tracks settings changes; deduplicated since command and id usually
121
- // coincide.
122
73
  const detectCommands = (): string[] => {
123
74
  const names = new Set<string>();
124
75
  for (const agent of agentRegistry?.agents ?? []) {
@@ -132,10 +83,6 @@ const plugin: JupyterFrontEndPlugin<IAgentTerminals> = {
132
83
  return Array.from(names);
133
84
  };
134
85
 
135
- // Whether a detected command/id belongs to a coding agent rather than an
136
- // editor. Only agent sessions get a latest-activity line (editor
137
- // terminals stay badge-only), and only they are offered as prompt
138
- // targets through `IAgentTerminals`.
139
86
  const isAgentCommand = (command: string): boolean =>
140
87
  agentRegistry?.agents.some(
141
88
  a => a.command === command || a.id === command
@@ -144,19 +91,14 @@ const plugin: JupyterFrontEndPlugin<IAgentTerminals> = {
144
91
  const registry = new SessionRegistry({
145
92
  serviceManager: app.serviceManager,
146
93
  tracker,
147
- // The shell tells the registry which widget is current, so the panel can
148
- // highlight the terminal that is the current main-area widget (and
149
- // nothing while a notebook or other widget is current instead).
150
94
  shell: app.shell,
151
95
  agentSessions,
152
96
  detectCommands,
153
97
  isAgentCommand
154
98
  });
155
99
 
156
- // Mirror the agent/editor detected in each open terminal onto its main-area
157
- // tab icon, so the tab matches its sidebar row. Re-running on every
158
- // `stateChanged` is safe: `Title.icon` ignores an unchanged assignment, so
159
- // the writes neither loop nor churn.
100
+ // `Title.icon` ignores an unchanged assignment, so re-running per
101
+ // stateChanged is cheap.
160
102
  const syncTabIcons = (): void => {
161
103
  tracker.forEach(widget => {
162
104
  const session = widget.content.session;
@@ -172,10 +114,8 @@ const plugin: JupyterFrontEndPlugin<IAgentTerminals> = {
172
114
  syncTabIcons();
173
115
 
174
116
  const onActivate = (name: string): void => {
175
- // `terminal:open` is the upstream entry point that handles both
176
- // sides of this: if a widget is already attached to the named
177
- // session it activates that tab, otherwise it spins up a fresh
178
- // widget connected to the live session.
117
+ // `terminal:open` activates an attached tab or spins up a fresh widget
118
+ // connected to the live session.
179
119
  void app.commands.execute('terminal:open', { name });
180
120
  };
181
121
 
@@ -188,10 +128,6 @@ const plugin: JupyterFrontEndPlugin<IAgentTerminals> = {
188
128
  };
189
129
 
190
130
  const onShutdownAll = (): void => {
191
- // Tearing down every session at once is hard to undo (each may be a
192
- // running agent), so confirm before calling the manager's bulk
193
- // shutdown. `runningChanged` then clears the list and the panel
194
- // re-renders empty.
195
131
  void showDialog({
196
132
  title: trans.__('Shut Down All Terminals?'),
197
133
  body: trans.__(
@@ -214,19 +150,8 @@ const plugin: JupyterFrontEndPlugin<IAgentTerminals> = {
214
150
  });
215
151
  };
216
152
 
217
- // The header "+" button. With the launcher's agent registry available
218
- // it drops down a menu of the available agents (reusing their registered
219
- // `xtralab:start-agent:<id>` commands, so the icons and labels match the
220
- // launcher exactly) followed by a separator and a plain terminal. Built
221
- // lazily and repopulated on each open so it always reflects the current,
222
- // settings-driven agent list. Without the registry (launcher disabled)
223
- // or with no agents installed, there is nothing to choose between, so
224
- // the button opens a plain terminal directly in one click.
225
- //
226
- // `MenuSvg` (not the bare Lumino `Menu`) is what every JupyterLab menu
227
- // uses: its renderer applies the `menuItem` LabIcon stylesheet, which
228
- // sizes the agent icons to 16px and centers them vertically — the bare
229
- // `Menu` renders the raw, oversized, misaligned SVGs.
153
+ // `MenuSvg`, not the bare Lumino `Menu`: its renderer applies the `menuItem`
154
+ // LabIcon stylesheet — the bare menu renders raw, oversized SVGs.
230
155
  let newMenu: MenuSvg | null = null;
231
156
  const onCreate = (anchor: { x: number; y: number }): void => {
232
157
  const agents = agentRegistry?.agents ?? [];
@@ -256,15 +181,8 @@ const plugin: JupyterFrontEndPlugin<IAgentTerminals> = {
256
181
  onCreate
257
182
  });
258
183
 
259
- // Added to the left sidebar. The shipped `layout` setting in
260
- // jupyter-config/labconfig gives each sidebar widget a default rank —
261
- // this Terminals panel ranks first, so running agents sit one click
262
- // away at the top. That setting assigns rank only and pins no area, so
263
- // the "Move Widget" context menu can relocate the panel and the layout
264
- // restorer remembers where the user puts it. The `rank` here is the
265
- // in-code fallback used when the setting is absent. Sessions restored
266
- // from a previous lab run land via `runningChanged` once the terminal
267
- // manager is ready, which the panel's `UseSignal` picks up.
184
+ // The shipped labconfig `layout` setting ranks this panel first (rank only,
185
+ // no area pin, so "Move Widget" works); this rank is the fallback.
268
186
  app.shell.add(panel, 'left', { rank: 1 });
269
187
  if (restorer) {
270
188
  restorer.add(panel, panel.id);
@@ -280,9 +198,6 @@ const plugin: JupyterFrontEndPlugin<IAgentTerminals> = {
280
198
  panel.announceSections();
281
199
  }
282
200
 
283
- // The latest-activity line under each agent row is on by default; honour
284
- // the `showAgentActivity` setting so it can be turned off. Read on load and
285
- // re-applied on every change.
286
201
  if (settingRegistry) {
287
202
  settingRegistry
288
203
  .load(PLUGIN_ID)
@@ -293,9 +208,8 @@ const plugin: JupyterFrontEndPlugin<IAgentTerminals> = {
293
208
  );
294
209
  };
295
210
  applyActivitySetting();
296
- // Bind the slot to the panel so disposing the panel (which clears
297
- // its signal data) drops the connection — the disposed registry is
298
- // then never reached on a later settings change.
211
+ // Bound to the panel so disposing it drops the connection — the
212
+ // disposed registry is never reached on a later settings change.
299
213
  settings.changed.connect(applyActivitySetting, panel);
300
214
  })
301
215
  .catch(reason => {
@@ -317,9 +231,6 @@ const plugin: JupyterFrontEndPlugin<IAgentTerminals> = {
317
231
  }
318
232
  };
319
233
 
320
- /**
321
- * Read a boolean setting value, falling back when it is missing or invalid.
322
- */
323
234
  function boolOption(value: unknown, fallback: boolean): boolean {
324
235
  return typeof value === 'boolean' ? value : fallback;
325
236
  }