@theia/ai-core-ui 1.75.0-next.8 → 1.75.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 (113) hide show
  1. package/lib/browser/ai-configuration/ai-configuration-category-registry.d.ts +29 -0
  2. package/lib/browser/ai-configuration/ai-configuration-category-registry.d.ts.map +1 -0
  3. package/lib/browser/ai-configuration/ai-configuration-category-registry.js +83 -0
  4. package/lib/browser/ai-configuration/ai-configuration-category-registry.js.map +1 -0
  5. package/lib/browser/ai-configuration/ai-configuration-category-registry.spec.d.ts +2 -0
  6. package/lib/browser/ai-configuration/ai-configuration-category-registry.spec.d.ts.map +1 -0
  7. package/lib/browser/ai-configuration/ai-configuration-category-registry.spec.js +122 -0
  8. package/lib/browser/ai-configuration/ai-configuration-category-registry.spec.js.map +1 -0
  9. package/lib/browser/ai-configuration/ai-configuration-category.d.ts +204 -0
  10. package/lib/browser/ai-configuration/ai-configuration-category.d.ts.map +1 -0
  11. package/lib/browser/ai-configuration/ai-configuration-category.js +86 -0
  12. package/lib/browser/ai-configuration/ai-configuration-category.js.map +1 -0
  13. package/lib/browser/ai-configuration/ai-configuration-selection-model.d.ts +15 -0
  14. package/lib/browser/ai-configuration/ai-configuration-selection-model.d.ts.map +1 -0
  15. package/lib/browser/ai-configuration/ai-configuration-selection-model.js +44 -0
  16. package/lib/browser/ai-configuration/ai-configuration-selection-model.js.map +1 -0
  17. package/lib/browser/ai-configuration/ai-configuration-setting-commands.d.ts +48 -0
  18. package/lib/browser/ai-configuration/ai-configuration-setting-commands.d.ts.map +1 -0
  19. package/lib/browser/ai-configuration/ai-configuration-setting-commands.js +98 -0
  20. package/lib/browser/ai-configuration/ai-configuration-setting-commands.js.map +1 -0
  21. package/lib/browser/ai-configuration/ai-configuration-setting-commands.spec.d.ts +2 -0
  22. package/lib/browser/ai-configuration/ai-configuration-setting-commands.spec.d.ts.map +1 -0
  23. package/lib/browser/ai-configuration/ai-configuration-setting-commands.spec.js +70 -0
  24. package/lib/browser/ai-configuration/ai-configuration-setting-commands.spec.js.map +1 -0
  25. package/lib/browser/ai-configuration/components/ai-configuration-components.spec.d.ts +2 -0
  26. package/lib/browser/ai-configuration/components/ai-configuration-components.spec.d.ts.map +1 -0
  27. package/lib/browser/ai-configuration/components/ai-configuration-components.spec.js +596 -0
  28. package/lib/browser/ai-configuration/components/ai-configuration-components.spec.js.map +1 -0
  29. package/lib/browser/ai-configuration/components/ai-configuration-controls.d.ts +118 -0
  30. package/lib/browser/ai-configuration/components/ai-configuration-controls.d.ts.map +1 -0
  31. package/lib/browser/ai-configuration/components/ai-configuration-controls.js +191 -0
  32. package/lib/browser/ai-configuration/components/ai-configuration-controls.js.map +1 -0
  33. package/lib/browser/ai-configuration/components/ai-configuration-item-row.d.ts +57 -0
  34. package/lib/browser/ai-configuration/components/ai-configuration-item-row.d.ts.map +1 -0
  35. package/lib/browser/ai-configuration/components/ai-configuration-item-row.js +48 -0
  36. package/lib/browser/ai-configuration/components/ai-configuration-item-row.js.map +1 -0
  37. package/lib/browser/ai-configuration/components/ai-configuration-origin-badge.d.ts +49 -0
  38. package/lib/browser/ai-configuration/components/ai-configuration-origin-badge.d.ts.map +1 -0
  39. package/lib/browser/ai-configuration/components/ai-configuration-origin-badge.js +79 -0
  40. package/lib/browser/ai-configuration/components/ai-configuration-origin-badge.js.map +1 -0
  41. package/lib/browser/ai-configuration/components/ai-configuration-primitives.d.ts +161 -0
  42. package/lib/browser/ai-configuration/components/ai-configuration-primitives.d.ts.map +1 -0
  43. package/lib/browser/ai-configuration/components/ai-configuration-primitives.js +131 -0
  44. package/lib/browser/ai-configuration/components/ai-configuration-primitives.js.map +1 -0
  45. package/lib/browser/ai-configuration/components/ai-configuration-setting-row.d.ts +54 -0
  46. package/lib/browser/ai-configuration/components/ai-configuration-setting-row.d.ts.map +1 -0
  47. package/lib/browser/ai-configuration/components/ai-configuration-setting-row.js +77 -0
  48. package/lib/browser/ai-configuration/components/ai-configuration-setting-row.js.map +1 -0
  49. package/lib/browser/ai-configuration/components/ai-settings-row-service.d.ts +194 -0
  50. package/lib/browser/ai-configuration/components/ai-settings-row-service.d.ts.map +1 -0
  51. package/lib/browser/ai-configuration/components/ai-settings-row-service.js +352 -0
  52. package/lib/browser/ai-configuration/components/ai-settings-row-service.js.map +1 -0
  53. package/lib/browser/ai-configuration/components/ai-settings-row-service.spec.d.ts +2 -0
  54. package/lib/browser/ai-configuration/components/ai-settings-row-service.spec.d.ts.map +1 -0
  55. package/lib/browser/ai-configuration/components/ai-settings-row-service.spec.js +233 -0
  56. package/lib/browser/ai-configuration/components/ai-settings-row-service.spec.js.map +1 -0
  57. package/lib/browser/ai-configuration/components/ai-settings-row.d.ts +50 -0
  58. package/lib/browser/ai-configuration/components/ai-settings-row.d.ts.map +1 -0
  59. package/lib/browser/ai-configuration/components/ai-settings-row.js +85 -0
  60. package/lib/browser/ai-configuration/components/ai-settings-row.js.map +1 -0
  61. package/lib/browser/ai-configuration/components/collapsible-list.d.ts +65 -0
  62. package/lib/browser/ai-configuration/components/collapsible-list.d.ts.map +1 -0
  63. package/lib/browser/ai-configuration/components/collapsible-list.js +82 -0
  64. package/lib/browser/ai-configuration/components/collapsible-list.js.map +1 -0
  65. package/lib/browser/ai-configuration/components/prompt-customization-dialogs.d.ts +35 -0
  66. package/lib/browser/ai-configuration/components/prompt-customization-dialogs.d.ts.map +1 -0
  67. package/lib/browser/ai-configuration/components/prompt-customization-dialogs.js +83 -0
  68. package/lib/browser/ai-configuration/components/prompt-customization-dialogs.js.map +1 -0
  69. package/lib/browser/ai-configuration/components/variant-set-card.d.ts +25 -0
  70. package/lib/browser/ai-configuration/components/variant-set-card.d.ts.map +1 -0
  71. package/lib/browser/ai-configuration/components/variant-set-card.js +133 -0
  72. package/lib/browser/ai-configuration/components/variant-set-card.js.map +1 -0
  73. package/lib/browser/ai-configuration/renderers/collection-category-renderer.d.ts +44 -0
  74. package/lib/browser/ai-configuration/renderers/collection-category-renderer.d.ts.map +1 -0
  75. package/lib/browser/ai-configuration/renderers/collection-category-renderer.js +106 -0
  76. package/lib/browser/ai-configuration/renderers/collection-category-renderer.js.map +1 -0
  77. package/lib/browser/ai-configuration/renderers/collection-category-renderer.spec.d.ts +2 -0
  78. package/lib/browser/ai-configuration/renderers/collection-category-renderer.spec.d.ts.map +1 -0
  79. package/lib/browser/ai-configuration/renderers/collection-category-renderer.spec.js +120 -0
  80. package/lib/browser/ai-configuration/renderers/collection-category-renderer.spec.js.map +1 -0
  81. package/lib/browser/ai-configuration/renderers/single-page-category-renderer.d.ts +15 -0
  82. package/lib/browser/ai-configuration/renderers/single-page-category-renderer.d.ts.map +1 -0
  83. package/lib/browser/ai-configuration/renderers/single-page-category-renderer.js +20 -0
  84. package/lib/browser/ai-configuration/renderers/single-page-category-renderer.js.map +1 -0
  85. package/lib/browser/ai-core-ui-frontend-module.d.ts +1 -0
  86. package/lib/browser/ai-core-ui-frontend-module.d.ts.map +1 -1
  87. package/lib/browser/ai-core-ui-frontend-module.js +11 -0
  88. package/lib/browser/ai-core-ui-frontend-module.js.map +1 -1
  89. package/package.json +6 -5
  90. package/src/browser/ai-configuration/ai-configuration-category-registry.spec.ts +137 -0
  91. package/src/browser/ai-configuration/ai-configuration-category-registry.ts +79 -0
  92. package/src/browser/ai-configuration/ai-configuration-category.ts +246 -0
  93. package/src/browser/ai-configuration/ai-configuration-selection-model.ts +42 -0
  94. package/src/browser/ai-configuration/ai-configuration-setting-commands.spec.ts +82 -0
  95. package/src/browser/ai-configuration/ai-configuration-setting-commands.ts +104 -0
  96. package/src/browser/ai-configuration/components/ai-configuration-components.spec.ts +655 -0
  97. package/src/browser/ai-configuration/components/ai-configuration-controls.tsx +382 -0
  98. package/src/browser/ai-configuration/components/ai-configuration-item-row.tsx +127 -0
  99. package/src/browser/ai-configuration/components/ai-configuration-origin-badge.tsx +114 -0
  100. package/src/browser/ai-configuration/components/ai-configuration-primitives.tsx +359 -0
  101. package/src/browser/ai-configuration/components/ai-configuration-setting-row.tsx +154 -0
  102. package/src/browser/ai-configuration/components/ai-settings-row-service.spec.ts +275 -0
  103. package/src/browser/ai-configuration/components/ai-settings-row-service.ts +401 -0
  104. package/src/browser/ai-configuration/components/ai-settings-row.tsx +176 -0
  105. package/src/browser/ai-configuration/components/collapsible-list.tsx +205 -0
  106. package/src/browser/ai-configuration/components/prompt-customization-dialogs.ts +89 -0
  107. package/src/browser/ai-configuration/components/variant-set-card.tsx +200 -0
  108. package/src/browser/ai-configuration/renderers/collection-category-renderer.spec.ts +126 -0
  109. package/src/browser/ai-configuration/renderers/collection-category-renderer.tsx +164 -0
  110. package/src/browser/ai-configuration/renderers/single-page-category-renderer.tsx +41 -0
  111. package/src/browser/ai-core-ui-frontend-module.ts +14 -1
  112. package/src/browser/style/ai-configuration-components.css +1410 -0
  113. package/src/browser/style/index.css +17 -0
@@ -0,0 +1,1410 @@
1
+ /********************************************************************************
2
+ * Copyright (C) 2026 EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * This Source Code may also be made available under the following Secondary
9
+ * Licenses when the conditions for such availability set forth in the Eclipse
10
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ * with the GNU Classpath Exception which is available at
12
+ * https://www.gnu.org/software/classpath/license.html.
13
+ *
14
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ ********************************************************************************/
16
+
17
+ /* Detail page frame. Every category body is centered in a bounded column with a consistent
18
+ look (adopted from the former "AI Features" General/Models page). */
19
+ .ai-configuration-page {
20
+ display: flex;
21
+ flex-direction: column;
22
+ gap: calc(var(--theia-ui-padding) * 2);
23
+ /* `width: 100%` (capped by `max-width`) keeps the column pinned to the pane width. Without it the
24
+ centered, max-width block shrink-wraps to its content inside the scrolling flex detail body, so
25
+ filtering a list down to a single narrow row would visibly narrow the whole page. */
26
+ width: 100%;
27
+ max-width: 860px;
28
+ margin: 0 auto;
29
+ box-sizing: border-box;
30
+ padding-bottom: calc(var(--theia-ui-padding) * 4);
31
+ }
32
+
33
+ /* Section */
34
+ .ai-configuration-section {
35
+ display: flex;
36
+ flex-direction: column;
37
+ gap: var(--theia-ui-padding);
38
+ }
39
+
40
+ .ai-configuration-section-title {
41
+ display: flex;
42
+ align-items: baseline;
43
+ gap: var(--theia-ui-padding);
44
+ padding-bottom: calc(var(--theia-ui-padding) / 2);
45
+ border-bottom: var(--theia-border-width) solid var(--theia-widget-border);
46
+ }
47
+
48
+ .ai-configuration-section-title-text {
49
+ font-size: var(--theia-ui-font-size2);
50
+ font-weight: 600;
51
+ }
52
+
53
+ /* A foldable section's whole title line is the toggle, so it takes the pointer and a focus ring. No hover
54
+ tint: the chevron already says it is foldable, and the read-only collapsible subsections of the agent
55
+ detail behave the same way. */
56
+ .ai-configuration-section-title.foldable {
57
+ cursor: pointer;
58
+ user-select: none;
59
+ border-radius: 3px;
60
+ }
61
+
62
+ .ai-configuration-section-title.foldable:focus-visible {
63
+ outline: 1px solid var(--theia-focusBorder);
64
+ outline-offset: 2px;
65
+ }
66
+
67
+ .ai-configuration-section-chevron {
68
+ align-self: center;
69
+ color: var(--theia-descriptionForeground);
70
+ }
71
+
72
+ /* Entry count next to the title: a neutral pill, so a folded section still states its size. The border is
73
+ drawn from `widget.border`, which the high-contrast themes define (and other themes do not), because the
74
+ badge background is black there and would otherwise merge into the page. */
75
+ .ai-configuration-section-count {
76
+ align-self: center;
77
+ padding: 0 6px;
78
+ border-radius: 999px;
79
+ background-color: var(--theia-badge-background);
80
+ color: var(--theia-badge-foreground);
81
+ font-size: var(--theia-ui-font-size0);
82
+ border: var(--theia-border-width) solid var(--theia-widget-border, transparent);
83
+ }
84
+
85
+ .ai-configuration-section-subtitle {
86
+ color: var(--theia-descriptionForeground);
87
+ font-size: var(--theia-ui-font-size0);
88
+ }
89
+
90
+ /* Right-aligned actions on a section's title line (e.g. the tools "copy all" toolbar). */
91
+ .ai-configuration-section-title-actions {
92
+ margin-left: auto;
93
+ align-self: center;
94
+ display: inline-flex;
95
+ gap: calc(var(--theia-ui-padding) / 2);
96
+ }
97
+
98
+ .ai-configuration-section-content {
99
+ display: flex;
100
+ flex-direction: column;
101
+ gap: calc(var(--theia-ui-padding) * 1.5);
102
+ }
103
+
104
+ /* Settings row: title and description on the left, a control on the right (or full-width below). The
105
+ left gutter mirrors the Settings UI: a hover-revealed gear on the far left, then the modified indicator
106
+ line at the content's left edge (gear OUTSIDE the line, to its left), then the content. The left
107
+ padding reserves that gutter so the gear never shifts the title. */
108
+ .ai-settings-row {
109
+ position: relative;
110
+ /* The row box begins at the modified indicator (its left padding is cancelled by an equal negative left
111
+ margin), so the content lines up with the section title AND the hover background covers only the
112
+ content — it starts at the indicator and never extends into the gutter. The gear sits further left in
113
+ the margin (see `.ai-settings-row-actions`), outside the hover background, with only its own hover. */
114
+ padding: calc(var(--theia-ui-padding) * 1.5) var(--theia-ui-padding) calc(var(--theia-ui-padding) * 1.5) 8px;
115
+ margin: 2px 0 2px -8px;
116
+ border-radius: 4px;
117
+ }
118
+
119
+ .ai-settings-row:hover {
120
+ background: var(--theia-settings-rowHoverBackground);
121
+ }
122
+
123
+ /* Modified indicator: a thin vertical line at the row box's left edge (the content's left edge), mirroring
124
+ the Settings UI's gutter border. The gear sits to the LEFT of this, out in the margin. */
125
+ .ai-settings-row.modified::before {
126
+ content: "";
127
+ position: absolute;
128
+ left: 0;
129
+ top: calc(var(--theia-ui-padding) * 1.5);
130
+ bottom: calc(var(--theia-ui-padding) * 1.5);
131
+ width: 2px;
132
+ background: var(--theia-settings-modifiedItemIndicator, var(--theia-editorGutter-modifiedBackground, var(--theia-focusBorder)));
133
+ }
134
+
135
+ .ai-settings-row-top {
136
+ display: flex;
137
+ align-items: flex-start;
138
+ gap: calc(var(--theia-ui-padding) * 2);
139
+ }
140
+
141
+ .ai-settings-row-main {
142
+ flex: 1;
143
+ min-width: 0;
144
+ }
145
+
146
+ .ai-settings-row-title {
147
+ font-weight: 600;
148
+ display: flex;
149
+ align-items: center;
150
+ gap: calc(var(--theia-ui-padding) / 2);
151
+ }
152
+
153
+ /* Preference tag badges (e.g. "Experimental"), mirroring the Settings UI's `.preference-tag`. */
154
+ .ai-settings-row-tags {
155
+ display: inline-flex;
156
+ align-items: center;
157
+ gap: calc(var(--theia-ui-padding) / 2);
158
+ }
159
+
160
+ .ai-settings-row-tag {
161
+ padding: calc(var(--theia-ui-padding) / 8) calc(var(--theia-ui-padding) / 2);
162
+ font-size: 0.85em;
163
+ font-weight: normal;
164
+ font-style: italic;
165
+ color: var(--theia-descriptionForeground);
166
+ background-color: var(--theia-badge-background);
167
+ border-radius: calc(var(--theia-ui-padding) / 4);
168
+ border: 1px solid var(--theia-contrastBorder, transparent);
169
+ }
170
+
171
+ /* Gear affordance on the far left of the gutter, mirroring the Settings UI: it sits OUTSIDE (to the left
172
+ of) the modified indicator line, ending right at it, and never shifts the title. */
173
+ .ai-settings-row-actions {
174
+ position: absolute;
175
+ /* In the margin, left of the row box (and its hover background) and of the modified indicator. */
176
+ left: -24px;
177
+ top: calc(var(--theia-ui-padding) * 1.25);
178
+ display: inline-flex;
179
+ font-weight: normal;
180
+ }
181
+
182
+ .ai-settings-row-gear {
183
+ display: inline-flex;
184
+ align-items: center;
185
+ justify-content: center;
186
+ box-sizing: border-box;
187
+ width: 20px;
188
+ height: 20px;
189
+ /* Zero the default <button> padding so the hover background is a snug 20x20 square, not wider. */
190
+ padding: 0;
191
+ border: none;
192
+ background: none;
193
+ color: var(--theia-descriptionForeground);
194
+ cursor: pointer;
195
+ border-radius: 3px;
196
+ visibility: hidden;
197
+ }
198
+
199
+ .ai-settings-row:hover .ai-settings-row-gear,
200
+ .ai-settings-row-gear:focus-visible {
201
+ visibility: visible;
202
+ }
203
+
204
+ .ai-settings-row-gear:hover {
205
+ color: var(--theia-foreground);
206
+ background: var(--theia-list-hoverBackground);
207
+ }
208
+
209
+ .ai-settings-row-gear:focus-visible {
210
+ outline: 1px solid var(--theia-focusBorder);
211
+ }
212
+
213
+ .ai-settings-row-description {
214
+ color: var(--theia-descriptionForeground);
215
+ font-size: var(--theia-ui-font-size1);
216
+ line-height: 1.5;
217
+ margin-top: 4px;
218
+ max-width: 100ch;
219
+ }
220
+
221
+ .ai-settings-row-description p,
222
+ .ai-settings-row-description ul,
223
+ .ai-settings-row-description ol {
224
+ margin: 0;
225
+ }
226
+
227
+ /* Vertical rhythm between adjacent markdown blocks so long, structured descriptions
228
+ (paragraphs followed by lists) stay scannable instead of collapsing together. */
229
+ .ai-settings-row-description :is(p, ul, ol)+ :is(p, ul, ol) {
230
+ margin-top: calc(var(--theia-ui-padding) / 1.5);
231
+ }
232
+
233
+ .ai-settings-row-description ul,
234
+ .ai-settings-row-description ol {
235
+ padding-left: 1.6em;
236
+ }
237
+
238
+ .ai-settings-row-description li+li {
239
+ margin-top: 3px;
240
+ }
241
+
242
+ /* Keep nested lists snug under their parent item. */
243
+ .ai-settings-row-description li>ul,
244
+ .ai-settings-row-description li>ol {
245
+ margin-top: 3px;
246
+ }
247
+
248
+ .ai-settings-row-description a {
249
+ color: var(--theia-textLink-foreground);
250
+ }
251
+
252
+ .ai-settings-row-description code {
253
+ font-family: var(--theia-code-font-family);
254
+ font-size: var(--theia-ui-font-size0);
255
+ background: var(--theia-textCodeBlock-background);
256
+ border-radius: 3px;
257
+ padding: 0 4px;
258
+ }
259
+
260
+ .ai-settings-row-control {
261
+ flex-shrink: 0;
262
+ display: flex;
263
+ align-items: center;
264
+ gap: var(--theia-ui-padding);
265
+ }
266
+
267
+ .ai-settings-row-below {
268
+ margin-top: var(--theia-ui-padding);
269
+ }
270
+
271
+ /* Disabled enum select (SelectComponent has no whole-control disabled prop). */
272
+ .theia-select-component.ai-config-select.disabled {
273
+ pointer-events: none;
274
+ opacity: 0.5;
275
+ }
276
+
277
+ /* A settings-styled row that navigates instead of editing a value (kept for non-card lists). */
278
+ .ai-settings-nav-row {
279
+ display: block;
280
+ width: 100%;
281
+ text-align: left;
282
+ border: none;
283
+ background: none;
284
+ color: inherit;
285
+ font: inherit;
286
+ cursor: pointer;
287
+ }
288
+
289
+ .ai-settings-nav-row:focus-visible {
290
+ outline: 1px solid var(--theia-focusBorder);
291
+ outline-offset: -1px;
292
+ }
293
+
294
+ .ai-settings-nav-chevron {
295
+ align-self: center;
296
+ color: var(--theia-descriptionForeground);
297
+ }
298
+
299
+ /* ------------------------------------------------------------------------- *
300
+ * Unified form controls (shared across every AI configuration page).
301
+ * A given logical control renders the same everywhere; see
302
+ * `ai-configuration/components/ai-configuration-controls.tsx`.
303
+ * ------------------------------------------------------------------------- */
304
+
305
+ /* Text input */
306
+ .ai-config-input {
307
+ /* Fill the row up to the same max as the select, so a text input lines up with the select width. */
308
+ width: 100%;
309
+ min-width: 240px;
310
+ max-width: 480px;
311
+ border: 1px solid var(--theia-dropdown-border);
312
+ }
313
+
314
+ .ai-config-input-mono {
315
+ font-family: var(--theia-code-font-family);
316
+ font-size: var(--theia-ui-font-size1);
317
+ }
318
+
319
+ /* Wraps the input so a validation message can stack beneath it while the input keeps its own width. */
320
+ .ai-config-input-wrap {
321
+ display: flex;
322
+ flex-direction: column;
323
+ gap: calc(var(--theia-ui-padding) / 2);
324
+ min-width: 0;
325
+ width: 100%;
326
+ }
327
+
328
+ .ai-config-input.error {
329
+ border-color: var(--theia-inputValidation-errorBorder, var(--theia-errorForeground));
330
+ }
331
+
332
+ .ai-config-input-error {
333
+ color: var(--theia-errorForeground);
334
+ font-size: var(--theia-ui-font-size0);
335
+ }
336
+
337
+ /* Toggle switch */
338
+ .ai-config-switch {
339
+ /* `inline-block` so the fixed width/height apply in any context. As a bare <label> it would default to
340
+ `display: inline` (width/height ignored), which collapsed the absolutely-positioned track to zero in
341
+ non-flex contexts such as a table cell, leaving only the thumb visible. */
342
+ display: inline-block;
343
+ position: relative;
344
+ width: 36px;
345
+ height: 20px;
346
+ flex-shrink: 0;
347
+ cursor: pointer;
348
+ vertical-align: middle;
349
+ }
350
+
351
+ .ai-config-switch input {
352
+ position: absolute;
353
+ opacity: 0;
354
+ inset: 0;
355
+ margin: 0;
356
+ cursor: pointer;
357
+ }
358
+
359
+ .ai-config-switch-track {
360
+ position: absolute;
361
+ inset: 0;
362
+ /* Off state: a filled neutral pill (clearly visible on light and dark backgrounds); the on state fills
363
+ with the accent colour (see :checked). The thumb uses the editor background so it always contrasts. */
364
+ background: var(--theia-descriptionForeground);
365
+ /* Pill radius so the track is fully round at any height (base and large variants). */
366
+ border-radius: 999px;
367
+ transition: background 0.15s;
368
+ /* The high-contrast themes leave the fill colours below undefined, which left the switch as an (invisible)
369
+ empty pill. `contrastBorder` exists only in those themes, so this outlines the control there and changes
370
+ nothing elsewhere. Deliberately an outline and not a border: a border on the track would move the thumb,
371
+ which is positioned against the track's padding box, off centre. */
372
+ outline: 1px solid var(--theia-contrastBorder, transparent);
373
+ outline-offset: -1px;
374
+ }
375
+
376
+ .ai-config-switch-thumb {
377
+ position: absolute;
378
+ top: 2px;
379
+ left: 2px;
380
+ width: 16px;
381
+ height: 16px;
382
+ /* Editor background so the knob contrasts both the neutral (off) and accent (on) track on any theme. */
383
+ background: var(--theia-editor-background);
384
+ border-radius: 50%;
385
+ transition: left 0.15s;
386
+ /* Outlined in high contrast, where the knob and the track can otherwise be the same colour. An outline
387
+ rather than a border so the knob keeps its exact size and position in every theme. */
388
+ outline: 1px solid var(--theia-contrastBorder, transparent);
389
+ }
390
+
391
+ /* `button.background` is undefined in the dark high-contrast theme, which left the checked track unfilled
392
+ and the switch unreadable; `focusBorder` is defined in every theme, so it stands in there. */
393
+ .ai-config-switch input:checked+.ai-config-switch-track {
394
+ background: var(--theia-button-background, var(--theia-focusBorder));
395
+ }
396
+
397
+ .ai-config-switch input:checked+.ai-config-switch-track .ai-config-switch-thumb {
398
+ left: 18px;
399
+ }
400
+
401
+ .ai-config-switch input:focus-visible+.ai-config-switch-track {
402
+ outline: 2px solid var(--theia-focusBorder);
403
+ outline-offset: 2px;
404
+ }
405
+
406
+ .ai-config-switch input:disabled {
407
+ cursor: default;
408
+ }
409
+
410
+ .ai-config-switch-large {
411
+ width: 40px;
412
+ height: 22px;
413
+ }
414
+
415
+ .ai-config-switch-large .ai-config-switch-thumb {
416
+ width: 18px;
417
+ height: 18px;
418
+ }
419
+
420
+ .ai-config-switch-large input:checked+.ai-config-switch-track .ai-config-switch-thumb {
421
+ left: 20px;
422
+ }
423
+
424
+ /* Numeric stepper */
425
+ .ai-config-stepper-wrap {
426
+ display: inline-flex;
427
+ align-items: center;
428
+ gap: calc(var(--theia-ui-padding) / 1.5);
429
+ }
430
+
431
+ .ai-config-stepper {
432
+ display: inline-flex;
433
+ align-items: center;
434
+ /* Match the standard `.theia-input` box (min-height, border-radius) so the stepper is not taller than
435
+ the other inputs; only the − / + buttons are extra. */
436
+ min-height: 28px;
437
+ border: var(--theia-border-width) solid var(--theia-input-border, var(--theia-widget-border));
438
+ border-radius: 2px;
439
+ overflow: hidden;
440
+ background: var(--theia-input-background);
441
+ }
442
+
443
+ .ai-config-stepper:focus-within {
444
+ outline: 1px solid var(--theia-focusBorder);
445
+ outline-offset: -1px;
446
+ }
447
+
448
+ .ai-config-stepper-button {
449
+ width: 26px;
450
+ height: 24px;
451
+ border: none;
452
+ background: none;
453
+ cursor: pointer;
454
+ color: var(--theia-descriptionForeground);
455
+ font-size: var(--theia-ui-font-size2);
456
+ }
457
+
458
+ .ai-config-stepper-button:hover:not(:disabled) {
459
+ background: var(--theia-list-hoverBackground);
460
+ color: var(--theia-foreground);
461
+ }
462
+
463
+ .ai-config-stepper-button:disabled {
464
+ opacity: 0.5;
465
+ cursor: default;
466
+ }
467
+
468
+ .ai-config-stepper-input {
469
+ width: 52px;
470
+ border: none;
471
+ text-align: center;
472
+ font: inherit;
473
+ padding: 3px 0;
474
+ outline: none;
475
+ background: transparent;
476
+ color: var(--theia-input-foreground);
477
+ }
478
+
479
+ /* Enum select (the shared SelectComponent). Only constrain the width to line up with the other controls;
480
+ the padding, border, background and focus ring all come from core's `.theia-select-component`
481
+ (see core `select-component.css`). Re-declaring them here previously doubled the padding/border and made
482
+ the control noticeably taller than the standard Theia select. We only raise its `min-height` from core's
483
+ 23px to 28px so it lines up with the text and number inputs, and fill the row width to match the text
484
+ input. */
485
+ .ai-config-select {
486
+ box-sizing: border-box;
487
+ width: 100%;
488
+ min-width: 240px;
489
+ max-width: 480px;
490
+ min-height: 28px;
491
+ }
492
+
493
+ /* A reasoning-level select on a configuration page: the shared glyphs (defined with the chat input's
494
+ selector, which owns the level icons) are inset by this control's own padding, not the chat toolbar's, so
495
+ the off-level slash stays centered on the bulb. */
496
+ .ai-config-select.theia-ReasoningLevelSelector.theia-select-component {
497
+ /* `.theia-select-component`'s own `padding: 0 8px` from `@theia/core`, since this control does not
498
+ override it the way the chat toolbar's compact variant does. */
499
+ --theia-reasoning-glyph-inset: 8px;
500
+ }
501
+
502
+ /* Error state, e.g. a prompt variant selection that points at a template which no longer exists: the
503
+ closed control reads red so the invalid value is obvious without opening the dropdown. */
504
+ .ai-config-select.error {
505
+ outline-color: var(--theia-inputValidation-errorBorder, var(--theia-errorForeground));
506
+ border-color: var(--theia-inputValidation-errorBorder, var(--theia-errorForeground));
507
+ background-color: var(--theia-inputValidation-errorBackground, var(--theia-editor-background));
508
+ }
509
+
510
+ .ai-config-select.error .theia-select-component-label {
511
+ color: var(--theia-errorForeground);
512
+ }
513
+
514
+ /* String-array list editor — mirrors the Settings UI `.preference-array` look (values as removable rows plus
515
+ an "Add Value…" input) but self-contained here, so it does not depend on the preferences package's
516
+ `.theia-settings-container`-scoped styles. */
517
+ .ai-config-array {
518
+ list-style: none;
519
+ margin: 0;
520
+ padding: 0;
521
+ max-width: 480px;
522
+ }
523
+
524
+ .ai-config-array .preference-array-element {
525
+ display: flex;
526
+ justify-content: space-between;
527
+ align-items: center;
528
+ padding: calc(var(--theia-ui-padding) / 2) var(--theia-ui-padding);
529
+ border-bottom: var(--theia-panel-border) 1px solid;
530
+ }
531
+
532
+ /* The add-input row below carries its own full border, so the last value must not draw one too:
533
+ the two would otherwise stack into a visible double line. */
534
+ .ai-config-array .preference-array-element:has(+ .ai-config-array-input-row) {
535
+ border-bottom: none;
536
+ }
537
+
538
+ .ai-config-array .preference-array-element:hover {
539
+ background-color: var(--theia-list-hoverBackground);
540
+ }
541
+
542
+ .ai-config-array .preference-array-element-btn {
543
+ width: 1.5em;
544
+ height: 1.5em;
545
+ display: flex;
546
+ justify-content: center;
547
+ align-items: center;
548
+ }
549
+
550
+ /* The remove button only appears on row hover, matching the Settings UI. */
551
+ .ai-config-array .preference-array-element .remove-btn {
552
+ opacity: 0;
553
+ }
554
+
555
+ .ai-config-array .preference-array-element:hover .remove-btn {
556
+ opacity: 1;
557
+ }
558
+
559
+ .ai-config-array .preference-array-element-btn:hover {
560
+ background-color: var(--theia-list-hoverBackground);
561
+ cursor: pointer;
562
+ }
563
+
564
+ .ai-config-array-input-row {
565
+ display: flex;
566
+ align-items: center;
567
+ border: 1px solid var(--theia-dropdown-border);
568
+ }
569
+
570
+ /* Overlap the + button onto the input's reserved right padding, as the Settings UI does. */
571
+ .ai-config-array .codicon.codicon-add {
572
+ margin-left: calc((var(--theia-icon-size) + 4px) * -1);
573
+ margin-right: 4px;
574
+ width: var(--theia-icon-size);
575
+ height: var(--theia-icon-size);
576
+ }
577
+
578
+ .ai-config-array .preference-array-input {
579
+ width: 100%;
580
+ padding-right: calc(var(--theia-icon-size) + var(--theia-ui-padding));
581
+ }
582
+
583
+ /* Path input + Browse */
584
+ .ai-config-path-row {
585
+ display: flex;
586
+ gap: calc(var(--theia-ui-padding) / 1.5);
587
+ }
588
+
589
+ .ai-config-edit-in-settings {
590
+ display: inline-flex;
591
+ align-items: center;
592
+ gap: calc(var(--theia-ui-padding) / 2);
593
+ white-space: nowrap;
594
+ }
595
+
596
+ /* Status dot */
597
+ .ai-configuration-status {
598
+ display: inline-block;
599
+ width: 8px;
600
+ height: 8px;
601
+ border-radius: 50%;
602
+ }
603
+
604
+ .ai-configuration-status-on {
605
+ background-color: var(--theia-charts-green);
606
+ }
607
+
608
+ .ai-configuration-status-off {
609
+ background-color: var(--theia-descriptionForeground);
610
+ opacity: 0.5;
611
+ }
612
+
613
+ .ai-configuration-status-warn {
614
+ background-color: var(--theia-editorWarning-foreground);
615
+ }
616
+
617
+ .ai-configuration-status-error {
618
+ background-color: var(--theia-errorForeground);
619
+ }
620
+
621
+ /* Status badge (dot + label) */
622
+ .ai-configuration-status-badge {
623
+ display: inline-flex;
624
+ align-items: center;
625
+ gap: var(--theia-ui-padding);
626
+ white-space: nowrap;
627
+ }
628
+
629
+ .ai-configuration-status-badge-label {
630
+ color: var(--theia-descriptionForeground);
631
+ font-size: var(--theia-ui-font-size0);
632
+ }
633
+
634
+ /* Overview card grid */
635
+ /* Overview list of a category's children: full-width navigable rows that match the Skills / Variables list
636
+ entries — each is its own outlined, rounded box on the editor background (not a dark card), highlighting on
637
+ hover and opening the item. */
638
+ .ai-configuration-item-list {
639
+ display: flex;
640
+ flex-direction: column;
641
+ gap: calc(var(--theia-ui-padding) * 1.5);
642
+ }
643
+
644
+ .ai-configuration-item-row {
645
+ position: relative;
646
+ display: flex;
647
+ align-items: flex-start;
648
+ gap: var(--theia-ui-padding);
649
+ /* A touch more padding than the base ui-padding so the rows breathe like the Variables list entries. */
650
+ padding: calc(var(--theia-ui-padding) * 1.5) calc(var(--theia-ui-padding) * 1.5);
651
+ border: var(--theia-border-width) solid var(--theia-widget-border);
652
+ border-radius: 4px;
653
+ background-color: var(--theia-editor-background);
654
+ }
655
+
656
+ /* Modified indicator: a thin vertical bar at the row's left edge, mirroring `.ai-settings-row.modified`
657
+ and the Settings UI's gutter border. Overlays the left border (rounded to match) so it adds no layout shift. */
658
+ .ai-configuration-item-row.modified::before {
659
+ content: "";
660
+ position: absolute;
661
+ left: 0;
662
+ top: 0;
663
+ bottom: 0;
664
+ width: 2px;
665
+ border-top-left-radius: 6px;
666
+ border-bottom-left-radius: 6px;
667
+ background: var(--theia-settings-modifiedItemIndicator, var(--theia-editorGutter-modifiedBackground, var(--theia-focusBorder)));
668
+ }
669
+
670
+ /* Gear affordance in the row's left gutter, mirroring `.ai-settings-row-actions`: it sits OUTSIDE the card
671
+ (to the left of the modified indicator) so it never shifts or indents the row content, and is hidden
672
+ until the row is hovered/focused. */
673
+ .ai-configuration-item-row-actions {
674
+ position: absolute;
675
+ left: -24px;
676
+ top: 50%;
677
+ transform: translateY(-50%);
678
+ display: inline-flex;
679
+ }
680
+
681
+ .ai-configuration-item-row:hover .ai-settings-row-gear,
682
+ .ai-configuration-item-row .ai-settings-row-gear:focus-visible {
683
+ visibility: visible;
684
+ }
685
+
686
+ /* Clickable affordances apply only to navigable rows (those that open a detail page); rows that only host
687
+ an inline control (e.g. the Tools confirmation select) are not clickable. */
688
+ .ai-configuration-item-row.navigable {
689
+ cursor: pointer;
690
+ }
691
+
692
+ .ai-configuration-item-row.navigable:hover {
693
+ background-color: var(--theia-list-hoverBackground);
694
+ }
695
+
696
+ .ai-configuration-item-row.navigable:focus-visible {
697
+ outline: 1px solid var(--theia-focusBorder);
698
+ outline-offset: -1px;
699
+ }
700
+
701
+ .ai-configuration-item-row-icon {
702
+ color: var(--theia-icon-foreground);
703
+ /* Nudge the icon onto the label's baseline row. */
704
+ margin-top: 2px;
705
+ }
706
+
707
+ .ai-configuration-item-row-text {
708
+ display: flex;
709
+ flex-direction: column;
710
+ gap: 4px;
711
+ flex: 1;
712
+ min-width: 0;
713
+ }
714
+
715
+ /* The name line: the label, plus any provenance badges next to it. */
716
+ .ai-configuration-item-row-heading {
717
+ display: flex;
718
+ align-items: center;
719
+ gap: calc(var(--theia-ui-padding) / 2);
720
+ min-width: 0;
721
+ }
722
+
723
+ .ai-configuration-item-row-tags {
724
+ display: inline-flex;
725
+ align-items: center;
726
+ gap: calc(var(--theia-ui-padding) / 2);
727
+ /* Never squeezed: a long name ellipsizes instead of pushing the badge out of the row. */
728
+ flex: none;
729
+ }
730
+
731
+ .ai-configuration-item-row-label {
732
+ font-weight: 600;
733
+ /* Allows the ellipsis to kick in inside the flex heading rather than overflowing it. */
734
+ min-width: 0;
735
+ overflow: hidden;
736
+ text-overflow: ellipsis;
737
+ white-space: nowrap;
738
+ }
739
+
740
+ /* Label that links elsewhere (e.g. an agent capability pointing at the snippet it pulls in). Styled as a
741
+ link rather than a button so it does not compete with the row's own control. */
742
+ .ai-configuration-item-row-label.link {
743
+ /* Reset the native button chrome; the text keeps the label's own weight and truncation. */
744
+ padding: 0;
745
+ border: none;
746
+ background: none;
747
+ font: inherit;
748
+ font-weight: 600;
749
+ text-align: left;
750
+ color: var(--theia-textLink-foreground);
751
+ cursor: pointer;
752
+ }
753
+
754
+ .ai-configuration-item-row-label.link:hover {
755
+ text-decoration: underline;
756
+ }
757
+
758
+ .ai-configuration-item-row-label.link:focus-visible {
759
+ outline: 1px solid var(--theia-focusBorder);
760
+ outline-offset: 1px;
761
+ border-radius: 2px;
762
+ }
763
+
764
+ /* Code-style label for identifier rows (e.g. shell command patterns), matching the Variables list names. */
765
+ .ai-configuration-item-row-label.mono {
766
+ font-family: var(--theia-code-font-family);
767
+ font-weight: normal;
768
+ }
769
+
770
+ .ai-configuration-item-row-description {
771
+ color: var(--theia-descriptionForeground);
772
+ font-size: var(--theia-ui-font-size1);
773
+ overflow: hidden;
774
+ text-overflow: ellipsis;
775
+ display: -webkit-box;
776
+ -webkit-line-clamp: 2;
777
+ -webkit-box-orient: vertical;
778
+ }
779
+
780
+ .ai-configuration-item-row-trailing {
781
+ display: flex;
782
+ align-items: center;
783
+ gap: var(--theia-ui-padding);
784
+ margin-left: auto;
785
+ flex-shrink: 0;
786
+ }
787
+
788
+ .ai-configuration-item-row-chevron {
789
+ color: var(--theia-descriptionForeground);
790
+ }
791
+
792
+ /* Item detail header */
793
+ .ai-configuration-item-detail-header {
794
+ display: flex;
795
+ align-items: flex-start;
796
+ justify-content: space-between;
797
+ gap: var(--theia-ui-padding);
798
+ padding-bottom: var(--theia-ui-padding);
799
+ border-bottom: var(--theia-border-width) solid var(--theia-widget-border);
800
+ }
801
+
802
+ .ai-configuration-item-detail-header-heading {
803
+ display: flex;
804
+ align-items: center;
805
+ gap: var(--theia-ui-padding);
806
+ }
807
+
808
+ .ai-configuration-item-detail-header-icon {
809
+ color: var(--theia-icon-foreground);
810
+ /* Detail headers get a clearly larger icon than a body/section icon. */
811
+ font-size: 22px;
812
+ }
813
+
814
+ .ai-configuration-item-detail-header-titles {
815
+ display: flex;
816
+ flex-direction: column;
817
+ }
818
+
819
+ /* Keep the status badge on the title's line, right after the title text, instead of floating centered to
820
+ the far right of the whole title/subtitle block. */
821
+ .ai-configuration-item-detail-header-title-row {
822
+ display: flex;
823
+ align-items: center;
824
+ gap: var(--theia-ui-padding);
825
+ }
826
+
827
+ .ai-configuration-item-detail-header-title {
828
+ font-size: var(--theia-ui-font-size2);
829
+ font-weight: 600;
830
+ }
831
+
832
+ .ai-configuration-item-detail-header-subtitle {
833
+ color: var(--theia-descriptionForeground);
834
+ font-size: var(--theia-ui-font-size0);
835
+ }
836
+
837
+ .ai-configuration-item-detail-header-actions {
838
+ display: flex;
839
+ align-items: center;
840
+ gap: var(--theia-ui-padding);
841
+ }
842
+
843
+ /* Add action */
844
+ .ai-configuration-add-action {
845
+ display: inline-flex;
846
+ align-items: center;
847
+ gap: calc(var(--theia-ui-padding) / 2);
848
+ }
849
+
850
+ .ai-configuration-overview-actions {
851
+ display: flex;
852
+ }
853
+
854
+ /* Filter input */
855
+ .ai-configuration-filter-input {
856
+ position: relative;
857
+ display: flex;
858
+ align-items: center;
859
+ }
860
+
861
+ .ai-configuration-filter-input-icon {
862
+ position: absolute;
863
+ left: 6px;
864
+ color: var(--theia-descriptionForeground);
865
+ pointer-events: none;
866
+ }
867
+
868
+ .ai-configuration-filter-input .theia-input {
869
+ width: 100%;
870
+ padding-left: 24px;
871
+ /* Reserve room on the right for the clear button so text never slides under it. */
872
+ padding-right: 24px;
873
+ border: 1px solid var(--theia-dropdown-border);
874
+ }
875
+
876
+ .ai-configuration-filter-input-clear {
877
+ position: absolute;
878
+ right: 4px;
879
+ display: inline-flex;
880
+ align-items: center;
881
+ justify-content: center;
882
+ width: 18px;
883
+ height: 18px;
884
+ padding: 0;
885
+ border: none;
886
+ background: none;
887
+ border-radius: 3px;
888
+ color: var(--theia-descriptionForeground);
889
+ cursor: pointer;
890
+ }
891
+
892
+ .ai-configuration-filter-input-clear:hover {
893
+ color: var(--theia-foreground);
894
+ background: var(--theia-list-hoverBackground);
895
+ }
896
+
897
+ .ai-configuration-filter-input-clear:focus-visible {
898
+ outline: 1px solid var(--theia-focusBorder);
899
+ }
900
+
901
+ /* Empty state */
902
+ .ai-configuration-empty-state {
903
+ display: flex;
904
+ flex-direction: column;
905
+ align-items: center;
906
+ gap: var(--theia-ui-padding);
907
+ padding: calc(var(--theia-ui-padding) * 3);
908
+ color: var(--theia-descriptionForeground);
909
+ text-align: center;
910
+ }
911
+
912
+ .ai-configuration-empty-state-icon {
913
+ font-size: var(--theia-ui-font-size3);
914
+ opacity: 0.7;
915
+ }
916
+
917
+ /* ------------------------------------------------------------------------- *
918
+ * General ("AI Features") page specifics: the hero master-toggle card, the
919
+ * gating treatment for dependent settings, the provider status line and the
920
+ * cost/data disclosure. These build on the shared row/section primitives above.
921
+ * ------------------------------------------------------------------------- */
922
+
923
+ /* Hero master toggle card */
924
+ .ai-configuration-hero {
925
+ border: var(--theia-border-width) solid var(--theia-widget-border);
926
+ border-radius: 4px;
927
+ padding: calc(var(--theia-ui-padding) * 2);
928
+ background: var(--theia-editorWidget-background);
929
+ }
930
+
931
+ .ai-configuration-hero .ai-settings-row-top {
932
+ align-items: center;
933
+ }
934
+
935
+ .ai-configuration-hero .ai-settings-row-title {
936
+ font-size: var(--theia-ui-font-size2);
937
+ }
938
+
939
+ .ai-configuration-status-line {
940
+ display: flex;
941
+ align-items: center;
942
+ gap: calc(var(--theia-ui-padding) / 1.5);
943
+ margin-top: var(--theia-ui-padding);
944
+ font-size: var(--theia-ui-font-size1);
945
+ color: var(--theia-descriptionForeground);
946
+ }
947
+
948
+ .ai-configuration-status-line a {
949
+ color: var(--theia-textLink-foreground);
950
+ cursor: pointer;
951
+ }
952
+
953
+ /* Cost/data disclosure */
954
+ .ai-configuration-risks {
955
+ margin-top: var(--theia-ui-padding);
956
+ font-size: var(--theia-ui-font-size1);
957
+ color: var(--theia-descriptionForeground);
958
+ }
959
+
960
+ .ai-configuration-risks>summary {
961
+ cursor: pointer;
962
+ color: var(--theia-textLink-foreground);
963
+ font-weight: 500;
964
+ list-style: none;
965
+ display: inline-flex;
966
+ align-items: center;
967
+ gap: calc(var(--theia-ui-padding) / 2);
968
+ }
969
+
970
+ .ai-configuration-risks>summary::before {
971
+ content: "\25B8";
972
+ /* ▸ */
973
+ font-size: var(--theia-ui-font-size0);
974
+ transition: transform 0.15s;
975
+ }
976
+
977
+ .ai-configuration-risks[open]>summary::before {
978
+ transform: rotate(90deg);
979
+ }
980
+
981
+ .ai-configuration-risks>summary:focus-visible {
982
+ outline: 1px solid var(--theia-focusBorder);
983
+ outline-offset: 2px;
984
+ }
985
+
986
+ .ai-configuration-risk-body {
987
+ margin-top: calc(var(--theia-ui-padding) / 1.5);
988
+ padding: var(--theia-ui-padding);
989
+ background: var(--theia-inputValidation-warningBackground);
990
+ border: var(--theia-border-width) solid var(--theia-inputValidation-warningBorder, var(--theia-editorWarning-foreground));
991
+ border-radius: 4px;
992
+ color: var(--theia-foreground);
993
+ max-width: 80ch;
994
+ }
995
+
996
+ .ai-configuration-risk-body p {
997
+ margin: 0;
998
+ }
999
+
1000
+ .ai-configuration-risk-body a {
1001
+ color: var(--theia-textLink-foreground);
1002
+ }
1003
+
1004
+ /* Gating: dependent settings shown but visually/interactively disabled while the master toggle is off. */
1005
+ .ai-configuration-gate-note {
1006
+ display: flex;
1007
+ align-items: center;
1008
+ gap: calc(var(--theia-ui-padding) / 1.5);
1009
+ padding: calc(var(--theia-ui-padding) / 1.5) var(--theia-ui-padding);
1010
+ font-size: var(--theia-ui-font-size1);
1011
+ border-radius: 4px;
1012
+ border-left: 3px solid var(--theia-focusBorder);
1013
+ background: var(--theia-editorWidget-background);
1014
+ color: var(--theia-foreground);
1015
+ }
1016
+
1017
+ .ai-configuration-sections {
1018
+ display: flex;
1019
+ flex-direction: column;
1020
+ gap: calc(var(--theia-ui-padding) * 2);
1021
+ }
1022
+
1023
+ .ai-configuration-sections.ai-configuration-sections-off {
1024
+ opacity: 0.45;
1025
+ pointer-events: none;
1026
+ user-select: none;
1027
+ }
1028
+
1029
+ /* ---------------------------------------------------------------------------
1030
+ Prompt variant sets (agent detail) + skills / slash commands surfaces.
1031
+ --------------------------------------------------------------------------- */
1032
+
1033
+ /* Kind / scope badge (labeled pill) */
1034
+ .ai-configuration-kind-badge {
1035
+ display: inline-flex;
1036
+ align-items: center;
1037
+ gap: calc(var(--theia-ui-padding) / 2);
1038
+ padding: 1px 8px;
1039
+ border-radius: 10px;
1040
+ font-size: var(--theia-ui-font-size0);
1041
+ white-space: nowrap;
1042
+ background-color: var(--theia-badge-background);
1043
+ color: var(--theia-badge-foreground);
1044
+ }
1045
+
1046
+ .ai-configuration-kind-badge-outline {
1047
+ background-color: transparent;
1048
+ border: var(--theia-border-width) solid var(--theia-widget-border);
1049
+ color: var(--theia-descriptionForeground);
1050
+ }
1051
+
1052
+ .ai-configuration-kind-badge-icon {
1053
+ font-size: var(--theia-ui-font-size0);
1054
+ }
1055
+
1056
+ /* Origin badge: where an entry came from (an AI registry entry, an Agent Plugin). Shaped like the
1057
+ outline kind badge so provenance reads as one kind of annotation wherever it appears - in an overview
1058
+ list, on a detail header, on a collapsible row - and differentiated from a plain tag by its leading
1059
+ icon. `button` resets are explicit: the activatable variant is a real button. */
1060
+ .ai-configuration-origin-badges {
1061
+ display: inline-flex;
1062
+ align-items: center;
1063
+ gap: calc(var(--theia-ui-padding) / 2);
1064
+ }
1065
+
1066
+ .ai-configuration-origin-badge {
1067
+ display: inline-flex;
1068
+ align-items: center;
1069
+ gap: calc(var(--theia-ui-padding) / 2);
1070
+ margin: 0;
1071
+ padding: 1px 8px;
1072
+ border: var(--theia-border-width) solid var(--theia-widget-border);
1073
+ border-radius: 10px;
1074
+ background-color: transparent;
1075
+ color: var(--theia-descriptionForeground);
1076
+ font-family: inherit;
1077
+ font-size: var(--theia-ui-font-size0);
1078
+ white-space: nowrap;
1079
+ }
1080
+
1081
+ /* Link-coloured only when it leads somewhere, so the colour is the affordance rather than decoration. */
1082
+ .ai-configuration-origin-badge.activatable {
1083
+ color: var(--theia-textLink-foreground);
1084
+ cursor: pointer;
1085
+ }
1086
+
1087
+ .ai-configuration-origin-badge.activatable:hover {
1088
+ color: var(--theia-textLink-activeForeground);
1089
+ border-color: var(--theia-focusBorder);
1090
+ }
1091
+
1092
+ .ai-configuration-origin-badge.activatable:focus-visible {
1093
+ outline: 1px solid var(--theia-focusBorder);
1094
+ outline-offset: 1px;
1095
+ }
1096
+
1097
+ .ai-configuration-origin-badge-icon {
1098
+ font-size: var(--theia-ui-font-size0);
1099
+ }
1100
+
1101
+ /* Horizontal, wrapping row of chips/badges */
1102
+ .ai-configuration-chip-row {
1103
+ display: flex;
1104
+ flex-wrap: wrap;
1105
+ gap: calc(var(--theia-ui-padding) / 2);
1106
+ }
1107
+
1108
+ /* Prompt variant set row: the variant select plus inline edit/reset icon actions in the row's trailing slot. */
1109
+ .ai-variant-controls {
1110
+ display: flex;
1111
+ align-items: center;
1112
+ gap: calc(var(--theia-ui-padding) / 2);
1113
+ }
1114
+
1115
+ .ai-variant-action-button {
1116
+ display: inline-flex;
1117
+ align-items: center;
1118
+ justify-content: center;
1119
+ width: 24px;
1120
+ height: 24px;
1121
+ padding: 0;
1122
+ border: none;
1123
+ background: none;
1124
+ color: var(--theia-icon-foreground);
1125
+ cursor: pointer;
1126
+ border-radius: 4px;
1127
+ }
1128
+
1129
+ .ai-variant-action-button:hover {
1130
+ color: var(--theia-foreground);
1131
+ background: var(--theia-list-hoverBackground);
1132
+ }
1133
+
1134
+ .ai-variant-action-button:focus-visible {
1135
+ outline: 1px solid var(--theia-focusBorder);
1136
+ }
1137
+
1138
+ /* A page-level offer: an explanatory line plus one action. */
1139
+ .ai-configuration-callout {
1140
+ display: flex;
1141
+ align-items: center;
1142
+ gap: calc(var(--theia-ui-padding) * 2);
1143
+ margin-bottom: calc(var(--theia-ui-padding) * 2);
1144
+ padding: calc(var(--theia-ui-padding) * 1.5);
1145
+ background-color: var(--theia-editorInfo-background, var(--theia-editor-background));
1146
+ border: var(--theia-border-width) solid var(--theia-editorInfo-border, var(--theia-widget-border));
1147
+ border-radius: 3px;
1148
+ }
1149
+
1150
+ .ai-configuration-callout-text {
1151
+ flex: 1;
1152
+ line-height: var(--theia-content-line-height);
1153
+ }
1154
+
1155
+ /* A read-only value with its label and copy button (ids, paths, frontmatter entries). */
1156
+ .ai-configuration-value-row {
1157
+ display: flex;
1158
+ align-items: center;
1159
+ gap: var(--theia-ui-padding);
1160
+ min-width: 0;
1161
+ }
1162
+
1163
+ .ai-configuration-value-row-label {
1164
+ flex: 0 0 auto;
1165
+ color: var(--theia-descriptionForeground);
1166
+ font-size: var(--theia-ui-font-size0);
1167
+ }
1168
+
1169
+ .ai-configuration-value-row-field {
1170
+ flex: 0 1 auto;
1171
+ display: flex;
1172
+ align-items: center;
1173
+ gap: calc(var(--theia-ui-padding) / 2);
1174
+ min-width: 0;
1175
+ }
1176
+
1177
+ .ai-configuration-value-row-value {
1178
+ flex: 0 1 auto;
1179
+ min-width: 0;
1180
+ font-family: var(--theia-editor-font-family, monospace);
1181
+ color: var(--theia-foreground);
1182
+ background-color: var(--theia-editor-background);
1183
+ border: var(--theia-border-width) solid var(--theia-widget-border);
1184
+ border-radius: 4px;
1185
+ padding: 0 6px;
1186
+ overflow-wrap: break-word;
1187
+ }
1188
+
1189
+ .ai-configuration-value-row-copy {
1190
+ flex: 0 0 auto;
1191
+ width: 22px;
1192
+ height: 22px;
1193
+ display: inline-flex;
1194
+ align-items: center;
1195
+ justify-content: center;
1196
+ padding: 0;
1197
+ border: none;
1198
+ background: transparent;
1199
+ color: var(--theia-icon-foreground);
1200
+ border-radius: 3px;
1201
+ cursor: pointer;
1202
+ }
1203
+
1204
+ .ai-configuration-value-row-copy:hover {
1205
+ background-color: var(--theia-list-hoverBackground);
1206
+ outline: 1px dotted var(--theia-contrastActiveBorder, transparent);
1207
+ outline-offset: -1px;
1208
+ }
1209
+
1210
+ .ai-configuration-value-row-copy:focus-visible {
1211
+ outline: 1px solid var(--theia-focusBorder);
1212
+ }
1213
+
1214
+ /* Available to assistive tech only. */
1215
+ .ai-configuration-visually-hidden {
1216
+ position: absolute;
1217
+ width: 1px;
1218
+ height: 1px;
1219
+ padding: 0;
1220
+ margin: -1px;
1221
+ overflow: hidden;
1222
+ clip: rect(0, 0, 0, 0);
1223
+ white-space: nowrap;
1224
+ border: 0;
1225
+ }
1226
+
1227
+ /* Collapsible list (`collapsible-list.tsx`): a filterable list of expandable rows grouped under
1228
+ titled sections, as used by the Variables and the Skills & Slash Commands pages. */
1229
+ .ai-config-collapsible-list {
1230
+ display: flex;
1231
+ flex-direction: column;
1232
+ gap: calc(var(--theia-ui-padding) * 2);
1233
+ }
1234
+
1235
+ /* One-line explanation of what distinguishes the group's kind of entry, under the group title. */
1236
+ .ai-config-collapsible-group-description {
1237
+ color: var(--theia-descriptionForeground);
1238
+ font-size: var(--theia-ui-font-size0);
1239
+ }
1240
+
1241
+ .ai-config-collapsible-row {
1242
+ border: var(--theia-border-width) solid var(--theia-widget-border);
1243
+ border-radius: 6px;
1244
+ background-color: var(--theia-editorWidget-background);
1245
+ }
1246
+
1247
+ /* The whole header is the disclosure control (role="button"): the chevron, title, header action,
1248
+ description and count pills all sit on one clickable row. */
1249
+ .ai-config-collapsible-row-header {
1250
+ display: flex;
1251
+ align-items: center;
1252
+ gap: var(--theia-ui-padding);
1253
+ padding: var(--theia-ui-padding);
1254
+ background-color: var(--theia-editor-background);
1255
+ border-radius: 5px;
1256
+ cursor: pointer;
1257
+ transition: background-color 0.1s;
1258
+ }
1259
+
1260
+ .ai-config-collapsible-row-header:hover {
1261
+ background-color: var(--theia-list-hoverBackground);
1262
+ }
1263
+
1264
+ .ai-config-collapsible-row-header:focus-visible {
1265
+ outline: 1px solid var(--theia-focusBorder);
1266
+ outline-offset: -1px;
1267
+ }
1268
+
1269
+ .ai-config-collapsible-row-header.expanded {
1270
+ border-radius: 5px 5px 0 0;
1271
+ border-bottom: var(--theia-border-width) solid var(--theia-widget-border);
1272
+ }
1273
+
1274
+ .ai-config-collapsible-expansion-icon {
1275
+ color: var(--theia-descriptionForeground);
1276
+ flex: none;
1277
+ }
1278
+
1279
+ /* Titles are identifiers the user types elsewhere (a variable reference, a `/command`), so they are
1280
+ rendered in the editor font and the link colour rather than as plain prose. */
1281
+ .ai-config-collapsible-row-title {
1282
+ font-family: var(--theia-editor-font-family, monospace);
1283
+ color: var(--theia-textLink-foreground);
1284
+ font-weight: 500;
1285
+ white-space: nowrap;
1286
+ flex: none;
1287
+ }
1288
+
1289
+ .ai-config-collapsible-inline-description {
1290
+ color: var(--theia-descriptionForeground);
1291
+ overflow: hidden;
1292
+ text-overflow: ellipsis;
1293
+ white-space: nowrap;
1294
+ min-width: 0;
1295
+ flex: 1;
1296
+ }
1297
+
1298
+ /* Holds the inline description's place in the header while the row is expanded (the description moves into
1299
+ the body), so the title and count pills keep their positions and the header height stays constant. */
1300
+ .ai-config-collapsible-inline-description-spacer {
1301
+ flex: 1;
1302
+ min-width: 0;
1303
+ }
1304
+
1305
+ /* Collapsed rows summarise the payload with count pills (e.g. "2 arguments", "3 agents") rather than
1306
+ listing agent names, so the row always stays on a single line regardless of how many agents use it. */
1307
+ .ai-config-collapsible-row-meta {
1308
+ display: flex;
1309
+ align-items: center;
1310
+ gap: calc(var(--theia-ui-padding) / 2);
1311
+ flex: none;
1312
+ }
1313
+
1314
+ /* Neutral, fully-rounded pills differentiated by a leading icon (not colour) so they stay legible in
1315
+ every theme and don't rely on hue alone: a parameter glyph for arguments, an agent glyph for agents. */
1316
+ .ai-config-collapsible-count-pill {
1317
+ display: inline-flex;
1318
+ align-items: center;
1319
+ gap: calc(var(--theia-ui-padding) / 2);
1320
+ /* Use the badge's own foreground for enough contrast against the badge background (the muted
1321
+ descriptionForeground was hard to read on it). */
1322
+ color: var(--theia-badge-foreground);
1323
+ background-color: var(--theia-badge-background);
1324
+ border: var(--theia-border-width) solid var(--theia-widget-border);
1325
+ border-radius: 999px;
1326
+ padding: 0 8px;
1327
+ font-size: 0.85em;
1328
+ white-space: nowrap;
1329
+ }
1330
+
1331
+ /* Actions sit at the very trailing edge, after the pills, so every row has them in the same place. */
1332
+ .ai-config-collapsible-row-actions {
1333
+ display: flex;
1334
+ align-items: center;
1335
+ gap: calc(var(--theia-ui-padding) / 2);
1336
+ flex: none;
1337
+ }
1338
+
1339
+ /* Dimmed at rest and brought to full strength when the row is hovered or something inside it is
1340
+ focused, so the actions stay discoverable without competing with the row title. */
1341
+ .ai-config-collapsible-row-action {
1342
+ display: inline-flex;
1343
+ align-items: center;
1344
+ justify-content: center;
1345
+ border: none;
1346
+ background: transparent;
1347
+ color: var(--theia-icon-foreground);
1348
+ cursor: pointer;
1349
+ padding: calc(var(--theia-ui-padding) / 2);
1350
+ border-radius: 3px;
1351
+ opacity: 0.6;
1352
+ transition: opacity 0.1s, background-color 0.1s;
1353
+ }
1354
+
1355
+ .ai-config-collapsible-row-header:hover .ai-config-collapsible-row-action,
1356
+ .ai-config-collapsible-row-header:focus-within .ai-config-collapsible-row-action {
1357
+ opacity: 1;
1358
+ }
1359
+
1360
+ .ai-config-collapsible-row-action:hover {
1361
+ background-color: var(--theia-list-hoverBackground);
1362
+ }
1363
+
1364
+ .ai-config-collapsible-row-action:focus-visible {
1365
+ opacity: 1;
1366
+ outline: 1px solid var(--theia-focusBorder);
1367
+ outline-offset: 1px;
1368
+ }
1369
+
1370
+ .ai-config-collapsible-row-action:disabled {
1371
+ cursor: default;
1372
+ opacity: 0.3;
1373
+ }
1374
+
1375
+ /* Body content is indented to align under the row title (past the chevron + gap). */
1376
+ .ai-config-collapsible-row-body {
1377
+ padding: var(--theia-ui-padding);
1378
+ padding-left: calc(var(--theia-ui-padding) * 2 + 16px);
1379
+ display: flex;
1380
+ flex-direction: column;
1381
+ gap: calc(var(--theia-ui-padding) * 1.5);
1382
+ border-radius: 0 0 5px 5px;
1383
+ }
1384
+
1385
+ /* The full description, shown at the top of the expanded body as a wrapping paragraph (it is truncated to a
1386
+ single line in the collapsed header). Line-height keeps multi-line descriptions comfortably readable. */
1387
+ .ai-config-collapsible-full-description {
1388
+ margin: 0;
1389
+ color: var(--theia-descriptionForeground);
1390
+ line-height: 1.5;
1391
+ }
1392
+
1393
+ /* High contrast: every hover state above communicates through a background colour alone, and the
1394
+ high-contrast themes define neither `list.hoverBackground` nor `button.background`, so those states
1395
+ render as nothing at all. `contrastActiveBorder` is defined *only* in the high-contrast themes — the same
1396
+ colour VS Code uses to mark the hovered/active element — so this ring shows up there and stays invisible
1397
+ everywhere else. Kept in one block so the intent is stated once rather than repeated per rule. */
1398
+ .ai-settings-row:hover,
1399
+ .ai-settings-row-gear:hover,
1400
+ .ai-configuration-item-row.navigable:hover,
1401
+ .ai-configuration-filter-input-clear:hover,
1402
+ .ai-config-stepper-button:hover:not(:disabled),
1403
+ .ai-config-array .preference-array-element:hover,
1404
+ .ai-config-array .preference-array-element-btn:hover,
1405
+ .ai-variant-action-button:hover,
1406
+ .ai-config-collapsible-row-header:hover,
1407
+ .ai-config-collapsible-row-action:hover {
1408
+ outline: 1px dotted var(--theia-contrastActiveBorder, transparent);
1409
+ outline-offset: -1px;
1410
+ }