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.
Files changed (162) hide show
  1. package/README.md +37 -229
  2. package/lib/agentSessions.d.ts +6 -2
  3. package/lib/askAgent/editorSelection.d.ts +53 -0
  4. package/lib/askAgent/editorSelection.js +95 -0
  5. package/lib/askAgent/icons.d.ts +7 -0
  6. package/lib/askAgent/icons.js +15 -0
  7. package/lib/askAgent/index.d.ts +32 -0
  8. package/lib/askAgent/index.js +741 -0
  9. package/lib/askAgent/popup.d.ts +83 -0
  10. package/lib/askAgent/popup.js +221 -0
  11. package/lib/askAgent/prompt.d.ts +24 -0
  12. package/lib/askAgent/prompt.js +116 -0
  13. package/lib/askAgent/queue.d.ts +93 -0
  14. package/lib/askAgent/queue.js +207 -0
  15. package/lib/askAgent/queuePanel.d.ts +76 -0
  16. package/lib/askAgent/queuePanel.js +188 -0
  17. package/lib/askAgent/targetPicker.d.ts +58 -0
  18. package/lib/askAgent/targetPicker.js +74 -0
  19. package/lib/askAgent/tokens.d.ts +124 -0
  20. package/lib/askAgent/tokens.js +13 -0
  21. package/lib/commandBar/index.d.ts +12 -8
  22. package/lib/commandBar/index.js +58 -41
  23. package/lib/editorBreadcrumbs/index.js +9 -4
  24. package/lib/editorBreadcrumbs/widget.d.ts +7 -7
  25. package/lib/editorBreadcrumbs/widget.js +6 -8
  26. package/lib/fileBrowser/commands.d.ts +2 -8
  27. package/lib/fileBrowser/commands.js +39 -30
  28. package/lib/fileBrowser/contents.d.ts +8 -3
  29. package/lib/fileBrowser/fileBrowser.d.ts +2 -1
  30. package/lib/fileBrowser/widget.d.ts +5 -9
  31. package/lib/fileBrowser/widget.js +1 -1
  32. package/lib/fileTypeIcons/index.js +5 -2
  33. package/lib/git/api.d.ts +0 -26
  34. package/lib/git/api.js +2 -44
  35. package/lib/git/askRequest.d.ts +23 -0
  36. package/lib/git/askRequest.js +90 -0
  37. package/lib/git/commands.d.ts +14 -2
  38. package/lib/git/commands.js +16 -13
  39. package/lib/git/diffModel.d.ts +1 -9
  40. package/lib/git/diffModel.js +1 -1
  41. package/lib/git/diffProvider.js +8 -3
  42. package/lib/git/diffSurface.d.ts +19 -2
  43. package/lib/git/diffSurface.js +64 -18
  44. package/lib/git/diffTheme.d.ts +0 -4
  45. package/lib/git/diffTheme.js +1 -1
  46. package/lib/git/diffWidget.d.ts +9 -0
  47. package/lib/git/diffWidget.js +38 -10
  48. package/lib/git/imageDiff.d.ts +17 -4
  49. package/lib/git/imageDiff.js +90 -30
  50. package/lib/git/index.js +7 -2
  51. package/lib/git/notebookDiff.d.ts +10 -67
  52. package/lib/git/notebookDiff.js +62 -69
  53. package/lib/git/tokens.d.ts +5 -2
  54. package/lib/highlight/index.js +12 -8
  55. package/lib/index.js +2 -0
  56. package/lib/launcher/agents.d.ts +11 -1
  57. package/lib/launcher/agents.js +26 -8
  58. package/lib/launcher/commands.d.ts +6 -2
  59. package/lib/launcher/dashboard.d.ts +8 -1
  60. package/lib/launcher/dashboard.js +39 -33
  61. package/lib/launcher/editorRegistry.js +5 -3
  62. package/lib/launcher/editors.d.ts +24 -7
  63. package/lib/launcher/editors.js +14 -5
  64. package/lib/launcher/icons.d.ts +0 -37
  65. package/lib/launcher/icons.js +11 -12
  66. package/lib/launcher/index.js +5 -2
  67. package/lib/launcher/invocation.d.ts +0 -15
  68. package/lib/launcher/invocation.js +1 -1
  69. package/lib/launcher/schemaDefaults.d.ts +3 -1
  70. package/lib/launcher/schemaDefaults.js +3 -1
  71. package/lib/mimeData.d.ts +7 -0
  72. package/lib/mimeData.js +16 -0
  73. package/lib/omnibox/index.d.ts +4 -0
  74. package/lib/omnibox/index.js +43 -2
  75. package/lib/omnibox/model.d.ts +43 -14
  76. package/lib/omnibox/model.js +117 -14
  77. package/lib/omnibox/recents.d.ts +65 -0
  78. package/lib/omnibox/recents.js +109 -0
  79. package/lib/omnibox/tokens.d.ts +6 -2
  80. package/lib/omnibox/widget.d.ts +23 -6
  81. package/lib/omnibox/widget.js +26 -7
  82. package/lib/showOutput/index.js +15 -18
  83. package/lib/terminals/agentTerminals.d.ts +63 -0
  84. package/lib/terminals/agentTerminals.js +157 -0
  85. package/lib/terminals/index.d.ts +7 -1
  86. package/lib/terminals/index.js +50 -30
  87. package/lib/terminals/model.d.ts +11 -2
  88. package/lib/terminals/model.js +27 -8
  89. package/lib/terminals/tokens.d.ts +66 -0
  90. package/lib/terminals/tokens.js +7 -0
  91. package/lib/terminals/widget.d.ts +3 -6
  92. package/lib/terminals/widget.js +1 -1
  93. package/lib/topBar/index.js +3 -3
  94. package/lib/walkthrough/index.js +14 -3
  95. package/lib/walkthrough/panel.d.ts +12 -4
  96. package/lib/walkthrough/panel.js +9 -3
  97. package/package.json +49 -51
  98. package/schema/command-bar.json +10 -0
  99. package/schema/launcher.json +4 -4
  100. package/schema/omnibox.json +15 -0
  101. package/src/agentSessions.ts +6 -2
  102. package/src/askAgent/editorSelection.ts +138 -0
  103. package/src/askAgent/icons.ts +16 -0
  104. package/src/askAgent/index.ts +915 -0
  105. package/src/askAgent/popup.tsx +407 -0
  106. package/src/askAgent/prompt.ts +144 -0
  107. package/src/askAgent/queue.ts +269 -0
  108. package/src/askAgent/queuePanel.tsx +418 -0
  109. package/src/askAgent/targetPicker.tsx +209 -0
  110. package/src/askAgent/tokens.ts +139 -0
  111. package/src/commandBar/index.ts +75 -49
  112. package/src/editorBreadcrumbs/index.ts +14 -4
  113. package/src/editorBreadcrumbs/widget.ts +11 -9
  114. package/src/fileBrowser/commands.ts +45 -31
  115. package/src/fileBrowser/contents.ts +7 -3
  116. package/src/fileBrowser/fileBrowser.tsx +1 -1
  117. package/src/fileBrowser/widget.tsx +5 -3
  118. package/src/fileTypeIcons/index.ts +6 -3
  119. package/src/git/api.ts +2 -61
  120. package/src/git/askRequest.ts +113 -0
  121. package/src/git/commands.ts +41 -14
  122. package/src/git/diffModel.ts +1 -1
  123. package/src/git/diffProvider.tsx +11 -3
  124. package/src/git/diffSurface.tsx +114 -22
  125. package/src/git/diffTheme.ts +1 -1
  126. package/src/git/diffWidget.tsx +54 -7
  127. package/src/git/imageDiff.tsx +169 -58
  128. package/src/git/index.ts +10 -2
  129. package/src/git/notebookDiff.tsx +91 -57
  130. package/src/git/tokens.ts +4 -2
  131. package/src/highlight/index.ts +12 -8
  132. package/src/index.ts +2 -0
  133. package/src/launcher/agents.ts +31 -7
  134. package/src/launcher/commands.ts +6 -2
  135. package/src/launcher/dashboard.tsx +86 -38
  136. package/src/launcher/editorRegistry.ts +10 -4
  137. package/src/launcher/editors.ts +34 -9
  138. package/src/launcher/icons.ts +11 -12
  139. package/src/launcher/index.ts +5 -2
  140. package/src/launcher/invocation.ts +1 -1
  141. package/src/launcher/schemaDefaults.ts +3 -1
  142. package/src/mimeData.ts +20 -0
  143. package/src/omnibox/index.ts +48 -1
  144. package/src/omnibox/model.ts +173 -33
  145. package/src/omnibox/recents.ts +155 -0
  146. package/src/omnibox/tokens.ts +6 -2
  147. package/src/omnibox/widget.tsx +54 -13
  148. package/src/showOutput/index.ts +20 -23
  149. package/src/terminals/agentTerminals.ts +238 -0
  150. package/src/terminals/index.ts +54 -30
  151. package/src/terminals/model.ts +28 -7
  152. package/src/terminals/tokens.ts +77 -0
  153. package/src/terminals/widget.tsx +4 -2
  154. package/src/topBar/index.ts +12 -6
  155. package/src/walkthrough/index.ts +19 -4
  156. package/src/walkthrough/panel.ts +15 -5
  157. package/style/askAgent.css +544 -0
  158. package/style/commandBar.css +12 -33
  159. package/style/git.css +72 -31
  160. package/style/index.css +1 -0
  161. package/style/index.js +2 -0
  162. package/style/topBar.css +4 -4
@@ -7,19 +7,25 @@ import { ICommandPalette } from '@jupyterlab/apputils';
7
7
  import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
8
8
  import { ITranslator, nullTranslator } from '@jupyterlab/translation';
9
9
  import { tocIcon } from '@jupyterlab/ui-components';
10
+ import type { ReadonlyPartialJSONValue } from '@lumino/coreutils';
10
11
 
12
+ import { coerceData } from '../mimeData';
11
13
  import { IWalkthroughMedia, IWalkthroughStep, WalkthroughPanel } from './panel';
12
14
 
13
15
  const PLUGIN_ID = 'xtralab:walkthrough';
14
16
 
15
- /** Append a step to the read-only walkthrough panel. */
17
+ /**
18
+ * Append a step to the read-only walkthrough panel.
19
+ */
16
20
  const WALKTHROUGH_COMMAND = 'xtralab:walkthrough';
17
21
 
18
22
  const HIGHLIGHT_LINES_COMMAND = 'xtralab:highlight-lines';
19
23
 
20
24
  const PANEL_ID = 'xtralab-walkthrough';
21
25
 
22
- /** Pull a `{ mimeType, data }` media object out of a JSON command argument. */
26
+ /**
27
+ * Pull a `{ mimeType, data }` media object out of a JSON command argument.
28
+ */
23
29
  function readMedia(value: unknown): IWalkthroughMedia | undefined {
24
30
  if (
25
31
  value &&
@@ -27,8 +33,17 @@ function readMedia(value: unknown): IWalkthroughMedia | undefined {
27
33
  !Array.isArray(value) &&
28
34
  typeof (value as { mimeType?: unknown }).mimeType === 'string'
29
35
  ) {
30
- const media = value as { mimeType: string; data?: unknown };
31
- return { mimeType: media.mimeType, data: media.data as never };
36
+ const media = value as {
37
+ mimeType: string;
38
+ data?: ReadonlyPartialJSONValue;
39
+ };
40
+ if (media.data === undefined) {
41
+ return undefined;
42
+ }
43
+ return {
44
+ mimeType: media.mimeType,
45
+ data: coerceData(media.mimeType, media.data)
46
+ };
32
47
  }
33
48
  return undefined;
34
49
  }
@@ -6,16 +6,22 @@ import type { ReadonlyPartialJSONValue } from '@lumino/coreutils';
6
6
  import type { Message } from '@lumino/messaging';
7
7
  import { Panel, Widget } from '@lumino/widgets';
8
8
 
9
- /** Command the jump links dispatch; keeps the panel decoupled from the plugin. */
9
+ /**
10
+ * Command the jump links dispatch; keeps the panel decoupled from the plugin.
11
+ */
10
12
  const HIGHLIGHT_LINES_COMMAND = 'xtralab:highlight-lines';
11
13
 
12
- /** A rich visual embedded in a step (rendered through the rendermime registry). */
14
+ /**
15
+ * A rich visual embedded in a step (rendered through the rendermime registry).
16
+ */
13
17
  export interface IWalkthroughMedia {
14
18
  mimeType: string;
15
19
  data: ReadonlyPartialJSONValue;
16
20
  }
17
21
 
18
- /** One step of a walkthrough. Every field is optional, but a step needs at least one. */
22
+ /**
23
+ * One step of a walkthrough. Every field is optional, but a step needs at least one.
24
+ */
19
25
  export interface IWalkthroughStep {
20
26
  title?: string;
21
27
  body?: string;
@@ -51,7 +57,9 @@ export class WalkthroughPanel extends Panel {
51
57
  this.addClass('jp-xtralab-Walkthrough');
52
58
  }
53
59
 
54
- /** Remove every step, leaving an empty panel. */
60
+ /**
61
+ * Remove every step, leaving an empty panel.
62
+ */
55
63
  clear(): void {
56
64
  while (this.widgets.length > 0) {
57
65
  this.widgets[0].dispose();
@@ -68,7 +76,9 @@ export class WalkthroughPanel extends Panel {
68
76
  this.dispose();
69
77
  }
70
78
 
71
- /** Append a step and scroll it into view. */
79
+ /**
80
+ * Append a step and scroll it into view.
81
+ */
72
82
  async addStep(step: IWalkthroughStep): Promise<void> {
73
83
  const card = new Panel();
74
84
  card.addClass('jp-xtralab-Walkthrough-step');
@@ -0,0 +1,544 @@
1
+ /*
2
+ * Ask-agent surfaces (xtralab:ask-agent): the floating "Ask agent" pill that
3
+ * follows a code selection, the prompt popup it (or the diff gutter "+"
4
+ * button) opens, and the right-sidebar queue panel that reviews queued
5
+ * prompts. The pill and popup are attached to `document.body`, outside the
6
+ * shell, and carry `jp-ThemedContainer` so theme variables resolve; the
7
+ * queue panel lives inside the shell.
8
+ */
9
+
10
+ .jp-xtralab-AskAgent-pill {
11
+ position: fixed;
12
+ z-index: 10000;
13
+ display: none;
14
+ gap: 5px;
15
+ align-items: center;
16
+ padding: 3px 9px;
17
+ font-family: var(--jp-ui-font-family);
18
+ font-size: var(--jp-ui-font-size0);
19
+ color: var(--jp-ui-font-color1);
20
+ cursor: pointer;
21
+ background: var(--jp-layout-color1);
22
+ border: var(--jp-border-width) solid var(--jp-border-color1);
23
+ border-radius: 999px;
24
+ box-shadow: var(--jp-elevation-z2);
25
+ }
26
+
27
+ .jp-xtralab-AskAgent-pill:hover {
28
+ color: var(--jp-ui-font-color0);
29
+ background: var(--jp-layout-color2);
30
+ }
31
+
32
+ .jp-xtralab-AskAgent-pill:focus-visible {
33
+ outline: var(--jp-border-width) solid var(--jp-brand-color1);
34
+ outline-offset: 1px;
35
+ }
36
+
37
+ .jp-xtralab-AskAgent-pillIcon {
38
+ display: flex;
39
+ align-items: center;
40
+ }
41
+
42
+ .jp-xtralab-AskAgent-pillIcon svg {
43
+ width: 14px;
44
+ height: 14px;
45
+ }
46
+
47
+ /* The popup host widget node; the React tree renders the fixed card below. */
48
+ .jp-xtralab-AskAgent {
49
+ position: absolute;
50
+ }
51
+
52
+ .jp-xtralab-AskAgent-popup {
53
+ position: fixed;
54
+ z-index: 10000;
55
+ display: flex;
56
+ flex-direction: column;
57
+ width: min(400px, 92vw);
58
+ background: var(--jp-layout-color1);
59
+ border: var(--jp-border-width) solid var(--jp-border-color1);
60
+ border-radius: 6px;
61
+ box-shadow: var(--jp-elevation-z6);
62
+ }
63
+
64
+ .jp-xtralab-AskAgent-context {
65
+ padding: 7px 10px 5px;
66
+ overflow: hidden;
67
+ font-size: var(--jp-ui-font-size0);
68
+ color: var(--jp-ui-font-color2);
69
+ white-space: nowrap;
70
+ text-overflow: ellipsis;
71
+ }
72
+
73
+ .jp-xtralab-AskAgent-input {
74
+ margin: 0 10px;
75
+ padding: 6px 8px;
76
+ font-family: var(--jp-ui-font-family);
77
+ font-size: var(--jp-ui-font-size1);
78
+ color: var(--jp-ui-font-color0);
79
+ resize: none;
80
+ background: var(--jp-layout-color0);
81
+ border: var(--jp-border-width) solid var(--jp-border-color2);
82
+ border-radius: 4px;
83
+ }
84
+
85
+ .jp-xtralab-AskAgent-input:focus {
86
+ border-color: var(--jp-brand-color1);
87
+ outline: none;
88
+ }
89
+
90
+ .jp-xtralab-AskAgent-input::placeholder {
91
+ color: var(--jp-ui-font-color3);
92
+ }
93
+
94
+ .jp-xtralab-AskAgent-empty {
95
+ padding: 4px 10px 10px;
96
+ font-size: var(--jp-ui-font-size1);
97
+ color: var(--jp-ui-font-color2);
98
+ }
99
+
100
+ /*
101
+ * Target chips: "New terminal" plus one chip per terminal with a running
102
+ * agent. Present only while at least one agent terminal is running.
103
+ */
104
+ .jp-xtralab-AskAgent-targets {
105
+ display: flex;
106
+ flex-wrap: wrap;
107
+ gap: 4px;
108
+ align-items: center;
109
+ padding: 8px 10px 0;
110
+ }
111
+
112
+ .jp-xtralab-AskAgent-targetButton {
113
+ display: flex;
114
+ flex: 0 0 auto;
115
+ gap: 5px;
116
+ align-items: center;
117
+ max-width: 100%;
118
+ padding: 3px 9px;
119
+ font-family: var(--jp-ui-font-family);
120
+ font-size: var(--jp-ui-font-size0);
121
+ color: var(--jp-ui-font-color1);
122
+ cursor: pointer;
123
+ background: transparent;
124
+ border: var(--jp-border-width) solid var(--jp-border-color2);
125
+ border-radius: 999px;
126
+ }
127
+
128
+ .jp-xtralab-AskAgent-targetButton:hover {
129
+ background: var(--jp-layout-color2);
130
+ }
131
+
132
+ .jp-xtralab-AskAgent-targetButton.jp-mod-selected {
133
+ background: var(--jp-layout-color2);
134
+ border-color: var(--jp-brand-color1);
135
+ }
136
+
137
+ .jp-xtralab-AskAgent-targetButton:focus-visible {
138
+ outline: var(--jp-border-width) solid var(--jp-brand-color1);
139
+ outline-offset: 1px;
140
+ }
141
+
142
+ .jp-xtralab-AskAgent-targetIcon {
143
+ display: flex;
144
+ align-items: center;
145
+ }
146
+
147
+ .jp-xtralab-AskAgent-targetIcon svg {
148
+ width: 14px;
149
+ height: 14px;
150
+ }
151
+
152
+ .jp-xtralab-AskAgent-targetLabel {
153
+ max-width: 160px;
154
+ overflow: hidden;
155
+ white-space: nowrap;
156
+ text-overflow: ellipsis;
157
+ }
158
+
159
+ .jp-xtralab-AskAgent-targetName {
160
+ color: var(--jp-ui-font-color3);
161
+ }
162
+
163
+ .jp-xtralab-AskAgent-footer {
164
+ display: flex;
165
+ gap: 8px;
166
+ align-items: center;
167
+ justify-content: space-between;
168
+ padding: 8px 10px;
169
+ }
170
+
171
+ .jp-xtralab-AskAgent-agents {
172
+ display: flex;
173
+ gap: 4px;
174
+ align-items: center;
175
+ overflow-x: auto;
176
+ }
177
+
178
+ .jp-xtralab-AskAgent-agentButton {
179
+ display: flex;
180
+ flex: 0 0 auto;
181
+ align-items: center;
182
+ justify-content: center;
183
+ width: 26px;
184
+ height: 26px;
185
+ padding: 0;
186
+ cursor: pointer;
187
+ background: transparent;
188
+ border: var(--jp-border-width) solid transparent;
189
+ border-radius: 4px;
190
+ }
191
+
192
+ .jp-xtralab-AskAgent-agentButton:hover {
193
+ background: var(--jp-layout-color2);
194
+ }
195
+
196
+ .jp-xtralab-AskAgent-agentButton.jp-mod-selected {
197
+ background: var(--jp-layout-color2);
198
+ border-color: var(--jp-brand-color1);
199
+ }
200
+
201
+ .jp-xtralab-AskAgent-agentButton:focus-visible {
202
+ outline: var(--jp-border-width) solid var(--jp-brand-color1);
203
+ outline-offset: 1px;
204
+ }
205
+
206
+ .jp-xtralab-AskAgent-agentIcon {
207
+ display: flex;
208
+ align-items: center;
209
+ }
210
+
211
+ .jp-xtralab-AskAgent-agentIcon svg {
212
+ width: 16px;
213
+ height: 16px;
214
+ }
215
+
216
+ /*
217
+ * `margin-left: auto` keeps the action buttons pinned right even when the
218
+ * agent radiogroup is absent (an existing session is the selected target,
219
+ * so the agent choice is implied and the row is not rendered). The
220
+ * "Send to %1" label embeds the session title, which the running agent may
221
+ * grow long via its xterm title escape, so the buttons shrink and ellipsize
222
+ * rather than overflowing the popup.
223
+ */
224
+ .jp-xtralab-AskAgent-actions {
225
+ display: flex;
226
+ flex: 0 1 auto;
227
+ gap: 6px;
228
+ align-items: center;
229
+ min-width: 0;
230
+ margin-left: auto;
231
+ }
232
+
233
+ .jp-xtralab-AskAgent-queueButton {
234
+ flex: 0 0 auto;
235
+ padding: 4px 12px;
236
+ font-size: var(--jp-ui-font-size1);
237
+ color: var(--jp-ui-font-color1);
238
+ white-space: nowrap;
239
+ cursor: pointer;
240
+ background: transparent;
241
+ border: var(--jp-border-width) solid var(--jp-border-color2);
242
+ border-radius: 4px;
243
+ }
244
+
245
+ .jp-xtralab-AskAgent-queueButton:disabled {
246
+ cursor: default;
247
+ opacity: 0.5;
248
+ }
249
+
250
+ .jp-xtralab-AskAgent-queueButton:focus-visible {
251
+ outline: var(--jp-border-width) solid var(--jp-brand-color1);
252
+ outline-offset: 1px;
253
+ }
254
+
255
+ .jp-xtralab-AskAgent-queueButton:hover:enabled {
256
+ background: var(--jp-layout-color2);
257
+ }
258
+
259
+ /* The popup's send button and the panel's batch-send button match. */
260
+ .jp-xtralab-AskAgent-submit,
261
+ .jp-xtralab-AskAgentQueue-send {
262
+ flex: 0 1 auto;
263
+ min-width: 0;
264
+ padding: 4px 12px;
265
+ overflow: hidden;
266
+ font-size: var(--jp-ui-font-size1);
267
+ color: var(--jp-ui-inverse-font-color0);
268
+ white-space: nowrap;
269
+ text-overflow: ellipsis;
270
+ cursor: pointer;
271
+ background: var(--jp-brand-color1);
272
+ border: none;
273
+ border-radius: 4px;
274
+ }
275
+
276
+ .jp-xtralab-AskAgent-submit:disabled,
277
+ .jp-xtralab-AskAgentQueue-send:disabled {
278
+ cursor: default;
279
+ opacity: 0.5;
280
+ }
281
+
282
+ /* Inset panel-background ring so keyboard focus stays visible on the
283
+ * brand fill. */
284
+ .jp-xtralab-AskAgent-submit:focus-visible,
285
+ .jp-xtralab-AskAgentQueue-send:focus-visible {
286
+ outline: var(--jp-border-width) solid var(--jp-layout-color1);
287
+ outline-offset: -2px;
288
+ }
289
+
290
+ .jp-xtralab-AskAgent-submit:hover:enabled,
291
+ .jp-xtralab-AskAgentQueue-send:hover:enabled {
292
+ background: var(--jp-brand-color0);
293
+ }
294
+
295
+ /*
296
+ * Queue panel (right side area): the queued prompts awaiting a batch send,
297
+ * each with a jump-to-code context line, a snippet preview and an editable
298
+ * instruction, above a footer that picks the target and sends everything.
299
+ */
300
+ .jp-xtralab-AskAgentQueue {
301
+ display: flex;
302
+ background: var(--jp-layout-color1);
303
+ }
304
+
305
+ .jp-xtralab-AskAgentQueue-body {
306
+ display: flex;
307
+ flex: 1 1 auto;
308
+ flex-direction: column;
309
+ min-width: 0;
310
+ font-family: var(--jp-ui-font-family);
311
+ font-size: var(--jp-ui-font-size1);
312
+ color: var(--jp-ui-font-color1);
313
+ }
314
+
315
+ .jp-xtralab-AskAgentQueue-blank {
316
+ padding: 12px;
317
+ color: var(--jp-ui-font-color2);
318
+ }
319
+
320
+ /* `min-height: 0` lets the list shrink below its content height (a flex
321
+ * item's default min-height is its content), so a long queue scrolls here
322
+ * instead of pushing the footer out of the panel. */
323
+ .jp-xtralab-AskAgentQueue-list {
324
+ display: flex;
325
+ flex: 1 1 auto;
326
+ flex-direction: column;
327
+ gap: 8px;
328
+ min-height: 0;
329
+ margin: 0;
330
+ padding: 8px;
331
+ overflow-y: auto;
332
+ list-style: none;
333
+ }
334
+
335
+ .jp-xtralab-AskAgentQueue-item {
336
+ display: flex;
337
+ flex: 0 0 auto;
338
+ flex-direction: column;
339
+ gap: 6px;
340
+ padding: 8px;
341
+ background: var(--jp-layout-color0);
342
+ border: var(--jp-border-width) solid var(--jp-border-color2);
343
+ border-radius: 6px;
344
+ }
345
+
346
+ .jp-xtralab-AskAgentQueue-itemHeader {
347
+ display: flex;
348
+ gap: 4px;
349
+ align-items: center;
350
+ justify-content: space-between;
351
+ }
352
+
353
+ .jp-xtralab-AskAgentQueue-itemContext {
354
+ flex: 0 1 auto;
355
+ min-width: 0;
356
+ padding: 0;
357
+ overflow: hidden;
358
+ font-family: var(--jp-ui-font-family);
359
+ font-size: var(--jp-ui-font-size0);
360
+ color: var(--jp-ui-font-color2);
361
+ text-align: left;
362
+ white-space: nowrap;
363
+ text-overflow: ellipsis;
364
+ cursor: pointer;
365
+ background: transparent;
366
+ border: none;
367
+ }
368
+
369
+ .jp-xtralab-AskAgentQueue-itemContext:hover {
370
+ color: var(--jp-brand-color1);
371
+ text-decoration: underline;
372
+ }
373
+
374
+ .jp-xtralab-AskAgentQueue-itemContext:focus-visible {
375
+ outline: var(--jp-border-width) solid var(--jp-brand-color1);
376
+ outline-offset: 1px;
377
+ }
378
+
379
+ .jp-xtralab-AskAgentQueue-itemRemove {
380
+ display: flex;
381
+ flex: 0 0 auto;
382
+ align-items: center;
383
+ justify-content: center;
384
+ width: 20px;
385
+ height: 20px;
386
+ padding: 0;
387
+ cursor: pointer;
388
+ background: transparent;
389
+ border: none;
390
+ border-radius: 4px;
391
+ }
392
+
393
+ .jp-xtralab-AskAgentQueue-itemRemove:hover {
394
+ background: var(--jp-layout-color2);
395
+ }
396
+
397
+ .jp-xtralab-AskAgentQueue-itemRemove:focus-visible {
398
+ outline: var(--jp-border-width) solid var(--jp-brand-color1);
399
+ outline-offset: 1px;
400
+ }
401
+
402
+ .jp-xtralab-AskAgentQueue-itemRemoveIcon {
403
+ display: flex;
404
+ align-items: center;
405
+ }
406
+
407
+ .jp-xtralab-AskAgentQueue-itemRemoveIcon svg {
408
+ width: 14px;
409
+ height: 14px;
410
+ }
411
+
412
+ /* Clamped preview of the selected code; the context line above jumps to
413
+ * the real thing. */
414
+ .jp-xtralab-AskAgentQueue-snippet {
415
+ display: -webkit-box;
416
+ margin: 0;
417
+ padding: 4px 6px;
418
+ overflow: hidden;
419
+ font-family: var(--jp-code-font-family);
420
+ font-size: var(--jp-code-font-size);
421
+ line-height: var(--jp-code-line-height);
422
+ color: var(--jp-ui-font-color2);
423
+ white-space: pre-wrap;
424
+ overflow-wrap: anywhere;
425
+ background: var(--jp-layout-color1);
426
+ border-radius: 4px;
427
+ -webkit-box-orient: vertical;
428
+ -webkit-line-clamp: 4;
429
+ }
430
+
431
+ .jp-xtralab-AskAgentQueue-instruction {
432
+ padding: 6px 8px;
433
+ font-family: var(--jp-ui-font-family);
434
+ font-size: var(--jp-ui-font-size1);
435
+ color: var(--jp-ui-font-color0);
436
+ resize: vertical;
437
+ background: var(--jp-layout-color0);
438
+ border: var(--jp-border-width) solid var(--jp-border-color2);
439
+ border-radius: 4px;
440
+ }
441
+
442
+ .jp-xtralab-AskAgentQueue-instruction:focus {
443
+ border-color: var(--jp-brand-color1);
444
+ outline: none;
445
+ }
446
+
447
+ .jp-xtralab-AskAgentQueue-instruction::placeholder {
448
+ color: var(--jp-ui-font-color3);
449
+ }
450
+
451
+ /* An emptied-out instruction blocks the batch send; make the gap visible. */
452
+ .jp-xtralab-AskAgentQueue-instruction[aria-invalid='true'] {
453
+ border-color: var(--jp-warn-color1);
454
+ }
455
+
456
+ /* Each prompt's own destination — the agent icon plus a select whose
457
+ * closed text names the action ("Terminal 2 · Claude", "New terminal ·
458
+ * Codex"), so a mixed queue can be scanned without opening dropdowns. */
459
+ .jp-xtralab-AskAgentQueue-itemTargetRow {
460
+ display: flex;
461
+ gap: 6px;
462
+ align-items: center;
463
+ }
464
+
465
+ .jp-xtralab-AskAgentQueue-itemTargetIcon {
466
+ display: flex;
467
+ flex: 0 0 auto;
468
+ align-items: center;
469
+ width: 16px;
470
+ }
471
+
472
+ .jp-xtralab-AskAgentQueue-itemTargetIcon svg {
473
+ width: 16px;
474
+ height: 16px;
475
+ }
476
+
477
+ /* The select is core's jp-HTMLSelect (the notebook-toolbar dropdown);
478
+ * these rules only make it fill the row and ellipsize long labels. */
479
+ .jp-xtralab-AskAgentQueue-itemTarget {
480
+ flex: 1 1 auto;
481
+ min-width: 0;
482
+ }
483
+
484
+ .jp-xtralab-AskAgentQueue-itemTarget select {
485
+ width: 100%;
486
+ overflow: hidden;
487
+ text-overflow: ellipsis;
488
+ white-space: nowrap;
489
+ }
490
+
491
+ /* A destination that has gone away (closed terminal, removed agent)
492
+ * blocks the send; make the gap visible despite the borderless default.
493
+ * The doubled-up class outweighs core's `.jp-HTMLSelect.jp-DefaultStyle
494
+ * select` border reset regardless of stylesheet order. */
495
+ .jp-xtralab-AskAgentQueue-itemTarget.jp-HTMLSelect select[aria-invalid='true'] {
496
+ border: var(--jp-border-width) solid var(--jp-warn-color1);
497
+ border-radius: 4px;
498
+ }
499
+
500
+ .jp-xtralab-AskAgentQueue-footer {
501
+ display: flex;
502
+ flex: 0 0 auto;
503
+ flex-direction: column;
504
+ gap: 8px;
505
+ padding: 10px;
506
+ border-top: var(--jp-border-width) solid var(--jp-border-color2);
507
+ }
508
+
509
+ .jp-xtralab-AskAgentQueue-noTargets {
510
+ color: var(--jp-ui-font-color2);
511
+ }
512
+
513
+ .jp-xtralab-AskAgentQueue-actions {
514
+ display: flex;
515
+ gap: 8px;
516
+ align-items: center;
517
+ justify-content: space-between;
518
+ }
519
+
520
+ .jp-xtralab-AskAgentQueue-clear {
521
+ flex: 0 0 auto;
522
+ padding: 4px 8px;
523
+ font-size: var(--jp-ui-font-size1);
524
+ color: var(--jp-ui-font-color2);
525
+ cursor: pointer;
526
+ background: transparent;
527
+ border: none;
528
+ border-radius: 4px;
529
+ }
530
+
531
+ .jp-xtralab-AskAgentQueue-clear:disabled {
532
+ cursor: default;
533
+ opacity: 0.5;
534
+ }
535
+
536
+ .jp-xtralab-AskAgentQueue-clear:focus-visible {
537
+ outline: var(--jp-border-width) solid var(--jp-brand-color1);
538
+ outline-offset: 1px;
539
+ }
540
+
541
+ .jp-xtralab-AskAgentQueue-clear:hover:enabled {
542
+ color: var(--jp-ui-font-color1);
543
+ background: var(--jp-layout-color2);
544
+ }
@@ -1,35 +1,19 @@
1
- /* Centered command bar in the top area (xtralab:command-bar). */
1
+ /* Command bar pill in the top bar toolbar (xtralab:command-bar). */
2
2
 
3
3
  /*
4
- * The bar is an overlay centered over the whole top panel rather than a flex
5
- * item, so its position does not shift with the (variable) width of the menu
6
- * bar on its left or the sidebar toggle button on its right. `#jp-top-panel`
7
- * is a `.lm-Widget`, which Lumino renders `position: relative`, so this
8
- * absolute box is centered against the full width of the top bar.
4
+ * The widget is a settings-driven item of JupyterLab's top bar toolbar
5
+ * (`#jp-top-bar`, factory "TopBar"), declared in schema/command-bar.json with
6
+ * a rank past the toolbar's built-in spacer, so it sits at the trailing end of
7
+ * the toolbar next to the right-sidebar toggle button.
9
8
  *
10
- * `pointer-events: none` here (with `auto` restored on the pill below) keeps
11
- * only the pill clickable: the transparent strips above and below it let
12
- * clicks fall through to whatever sits beneath the overlay.
13
- *
14
- * The `z-index` must clear JupyterLab core's settings-driven "Topbar toolbar"
15
- * (`#jp-top-bar`, added to the top area at rank 900), which is a `.jp-Toolbar`
16
- * at `z-index: 8` that grows to fill the center and paints an opaque
17
- * `--jp-toolbar-background`. Sitting one above it lets the centered pill show
18
- * through; that toolbar is empty by default, so the overlay covers blank
19
- * space rather than hiding any toolbar items.
9
+ * The widget's root (`.jp-xtralab-CommandBar`) is a plain wrapper that takes
10
+ * the core `.jp-Toolbar > .jp-Toolbar-item` sizing — full toolbar height,
11
+ * centered flex — so it needs no rules of its own; the pill button inside
12
+ * keeps its own compact height. It is styled with the theme's input-field
13
+ * fill so it reads as a search box and tracks each theme's input styling
14
+ * across light and dark (a flat layout color is near-black in some dark
15
+ * themes).
20
16
  */
21
- .jp-xtralab-CommandBar {
22
- position: absolute;
23
- top: 0;
24
- bottom: 0;
25
- left: 50%;
26
- z-index: 9;
27
- display: flex;
28
- align-items: center;
29
- transform: translateX(-50%);
30
- pointer-events: none;
31
- }
32
-
33
17
  .jp-xtralab-CommandBar-button {
34
18
  display: flex;
35
19
  flex: 0 0 auto;
@@ -45,15 +29,10 @@
45
29
  color: var(--jp-ui-font-color2);
46
30
  text-align: left;
47
31
  cursor: pointer;
48
-
49
- /* The theme's input-field fill, so the pill reads as a search box and tracks
50
- each theme's input styling across light and dark (a flat layout color is
51
- near-black in some dark themes). */
52
32
  background: var(--jp-input-background);
53
33
  border: var(--jp-border-width) solid var(--jp-border-color1);
54
34
  border-radius: 10px;
55
35
  appearance: none;
56
- pointer-events: auto;
57
36
  }
58
37
 
59
38
  .jp-xtralab-CommandBar-button:hover {