@1agh/maude 0.45.0 → 0.45.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.
- package/apps/studio/acp/bridge.ts +585 -73
- package/apps/studio/acp/index.ts +172 -23
- package/apps/studio/acp/probe.ts +31 -7
- package/apps/studio/acp/transcript.ts +91 -5
- package/apps/studio/bin/_import-asset.mjs +35 -5
- package/apps/studio/client/panels/CapabilityBar.jsx +101 -0
- package/apps/studio/client/panels/ChatPanel.jsx +802 -133
- package/apps/studio/client/panels/ElicitationPrompt.jsx +429 -0
- package/apps/studio/client/panels/PermissionPrompt.jsx +119 -0
- package/apps/studio/client/panels/ReadinessList.jsx +17 -3
- package/apps/studio/client/panels/ToolGroup.jsx +79 -0
- package/apps/studio/client/panels/acp-capabilities.js +71 -0
- package/apps/studio/client/panels/acp-elicitation.js +194 -0
- package/apps/studio/client/panels/acp-runtime.js +248 -9
- package/apps/studio/client/panels/acp-usage.js +65 -0
- package/apps/studio/client/panels/transcript-view.js +36 -0
- package/apps/studio/client/styles/6-acp-chat.css +648 -11
- package/apps/studio/dist/client.bundle.js +1596 -1594
- package/apps/studio/dist/styles.css +1 -1
- package/apps/studio/generation/whisper-models.test.ts +28 -1
- package/apps/studio/generation/whisper-models.ts +22 -7
- package/apps/studio/http.ts +33 -2
- package/apps/studio/test/acp-bridge.test.ts +11 -6
- package/apps/studio/test/acp-capabilities.test.ts +123 -0
- package/apps/studio/test/acp-caps-bridge.test.ts +274 -0
- package/apps/studio/test/acp-elicitation-bridge.test.ts +475 -0
- package/apps/studio/test/acp-elicitation.test.ts +251 -0
- package/apps/studio/test/acp-permission-prompt.test.ts +77 -0
- package/apps/studio/test/acp-permission.test.ts +262 -0
- package/apps/studio/test/acp-toolgroup.test.ts +76 -0
- package/apps/studio/test/acp-transcript-view.test.ts +71 -0
- package/apps/studio/test/acp-transcript.test.ts +75 -2
- package/apps/studio/test/acp-usage-bridge.test.ts +136 -0
- package/apps/studio/test/acp-usage.test.ts +143 -0
- package/apps/studio/test/fixtures/mock-acp-agent-caps.mjs +158 -0
- package/apps/studio/test/fixtures/mock-acp-agent-elicit-flood.mjs +46 -0
- package/apps/studio/test/fixtures/mock-acp-agent-elicit-url.mjs +42 -0
- package/apps/studio/test/fixtures/mock-acp-agent-elicit.mjs +63 -0
- package/apps/studio/test/fixtures/mock-acp-agent-permission-flood.mjs +51 -0
- package/apps/studio/test/fixtures/mock-acp-agent-permission.mjs +50 -0
- package/apps/studio/test/fixtures/mock-acp-agent-usage.mjs +56 -0
- package/apps/studio/test/import-asset.test.ts +31 -3
- package/apps/studio/whats-new.json +34 -0
- package/cli/commands/design.mjs +107 -2
- package/cli/lib/pkg-root.mjs +42 -10
- package/cli/lib/pkg-root.test.mjs +33 -1
- package/package.json +11 -9
|
@@ -136,6 +136,7 @@
|
|
|
136
136
|
padding: var(--space-1);
|
|
137
137
|
}
|
|
138
138
|
.chat-menu-row {
|
|
139
|
+
position: relative;
|
|
139
140
|
display: flex;
|
|
140
141
|
align-items: center;
|
|
141
142
|
border-radius: var(--radius-xs);
|
|
@@ -167,18 +168,78 @@
|
|
|
167
168
|
text-overflow: ellipsis;
|
|
168
169
|
white-space: nowrap;
|
|
169
170
|
}
|
|
170
|
-
.chat-menu-
|
|
171
|
+
/* Inline rename input (Task C5) — same box model as .chat-menu-open so the
|
|
172
|
+
row doesn't jump when switching between the button and the input. */
|
|
173
|
+
.chat-menu-rename-input {
|
|
174
|
+
flex: 1;
|
|
175
|
+
min-width: 0;
|
|
176
|
+
appearance: none;
|
|
177
|
+
border: 1px solid var(--accent);
|
|
178
|
+
border-radius: var(--radius-xs);
|
|
179
|
+
background: var(--bg-1);
|
|
180
|
+
color: var(--fg-0);
|
|
181
|
+
font-family: var(--font-body);
|
|
182
|
+
font-size: var(--type-xs);
|
|
183
|
+
padding: var(--space-2);
|
|
184
|
+
margin: 2px;
|
|
185
|
+
outline: none;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/* Per-chat overflow (⋯ → Rename / Archive / Copy transcript / Delete). */
|
|
189
|
+
.chat-menu-overflow-wrap {
|
|
190
|
+
position: relative;
|
|
191
|
+
flex-shrink: 0;
|
|
192
|
+
}
|
|
193
|
+
.chat-menu-more {
|
|
171
194
|
appearance: none;
|
|
172
195
|
border: 0;
|
|
173
196
|
background: transparent;
|
|
174
197
|
cursor: pointer;
|
|
175
198
|
color: var(--fg-3);
|
|
176
199
|
display: inline-flex;
|
|
177
|
-
|
|
200
|
+
align-items: center;
|
|
201
|
+
justify-content: center;
|
|
202
|
+
width: 22px;
|
|
203
|
+
height: 22px;
|
|
204
|
+
padding: 0;
|
|
178
205
|
border-radius: var(--radius-xs);
|
|
179
206
|
flex-shrink: 0;
|
|
207
|
+
font-size: var(--type-sm);
|
|
208
|
+
}
|
|
209
|
+
.chat-menu-more:hover {
|
|
210
|
+
background: var(--bg-4, var(--bg-3));
|
|
211
|
+
color: var(--fg-0);
|
|
212
|
+
}
|
|
213
|
+
.chat-menu-overflow {
|
|
214
|
+
position: absolute;
|
|
215
|
+
top: calc(100% + 2px);
|
|
216
|
+
right: 0;
|
|
217
|
+
z-index: 52;
|
|
218
|
+
display: flex;
|
|
219
|
+
flex-direction: column;
|
|
220
|
+
min-width: 150px;
|
|
221
|
+
padding: var(--space-1);
|
|
222
|
+
background: var(--bg-2);
|
|
223
|
+
border: 1px solid var(--border-default);
|
|
224
|
+
border-radius: var(--radius-sm);
|
|
225
|
+
box-shadow: var(--shadow-lg);
|
|
226
|
+
}
|
|
227
|
+
.chat-menu-overflow button {
|
|
228
|
+
appearance: none;
|
|
229
|
+
border: 0;
|
|
230
|
+
background: transparent;
|
|
231
|
+
text-align: left;
|
|
232
|
+
cursor: pointer;
|
|
233
|
+
color: var(--fg-1);
|
|
234
|
+
font-family: var(--font-body);
|
|
235
|
+
font-size: var(--type-xs);
|
|
236
|
+
padding: var(--space-2);
|
|
237
|
+
border-radius: var(--radius-xs);
|
|
180
238
|
}
|
|
181
|
-
.chat-menu-
|
|
239
|
+
.chat-menu-overflow button:hover {
|
|
240
|
+
background: var(--bg-3);
|
|
241
|
+
}
|
|
242
|
+
.chat-menu-overflow-danger {
|
|
182
243
|
color: var(--status-error);
|
|
183
244
|
}
|
|
184
245
|
.chat-dot {
|
|
@@ -197,6 +258,20 @@
|
|
|
197
258
|
.chat-dot--off {
|
|
198
259
|
background: var(--border-strong);
|
|
199
260
|
}
|
|
261
|
+
/* Transcript view label (Task C4/C5) — a bare unlabeled select read as
|
|
262
|
+
unexplained UI in dogfooding; this small caption fixes that. */
|
|
263
|
+
.chat-view-label {
|
|
264
|
+
display: flex;
|
|
265
|
+
align-items: center;
|
|
266
|
+
gap: 4px;
|
|
267
|
+
flex-shrink: 0;
|
|
268
|
+
}
|
|
269
|
+
.chat-view-label-tx {
|
|
270
|
+
font-family: var(--font-mono);
|
|
271
|
+
font-size: var(--type-xs);
|
|
272
|
+
color: var(--fg-3);
|
|
273
|
+
white-space: nowrap;
|
|
274
|
+
}
|
|
200
275
|
.chat-newbtn {
|
|
201
276
|
appearance: none;
|
|
202
277
|
border: 1px solid var(--border-default);
|
|
@@ -239,6 +314,9 @@
|
|
|
239
314
|
.chat-statusrow-cc {
|
|
240
315
|
color: var(--fg-1);
|
|
241
316
|
}
|
|
317
|
+
.chat-statusrow-spacer {
|
|
318
|
+
flex: 1;
|
|
319
|
+
}
|
|
242
320
|
.chat-status-dot {
|
|
243
321
|
width: 7px;
|
|
244
322
|
height: 7px;
|
|
@@ -398,6 +476,7 @@
|
|
|
398
476
|
|
|
399
477
|
/* Messages */
|
|
400
478
|
.chat-msg {
|
|
479
|
+
position: relative;
|
|
401
480
|
display: flex;
|
|
402
481
|
flex-direction: column;
|
|
403
482
|
gap: var(--space-2);
|
|
@@ -457,6 +536,58 @@
|
|
|
457
536
|
padding-top: var(--space-3);
|
|
458
537
|
}
|
|
459
538
|
|
|
539
|
+
/* Per-message hover actions (Task C2 — Copy / Retry). Absolutely positioned
|
|
540
|
+
so it never reflows the bubble; hover- AND focus-revealed (keyboard users
|
|
541
|
+
tab to the buttons, which triggers :focus-within even without a pointer). */
|
|
542
|
+
.chat-msg-actions {
|
|
543
|
+
position: absolute;
|
|
544
|
+
top: calc(-1 * var(--space-2));
|
|
545
|
+
right: 0;
|
|
546
|
+
display: flex;
|
|
547
|
+
gap: 2px;
|
|
548
|
+
padding: 2px;
|
|
549
|
+
border: 1px solid var(--border-subtle);
|
|
550
|
+
border-radius: var(--radius-sm);
|
|
551
|
+
background: var(--bg-2);
|
|
552
|
+
opacity: 0;
|
|
553
|
+
pointer-events: none;
|
|
554
|
+
transition: opacity var(--dur-fast, 120ms) ease;
|
|
555
|
+
}
|
|
556
|
+
.chat-msg:hover .chat-msg-actions,
|
|
557
|
+
.chat-msg:focus-within .chat-msg-actions {
|
|
558
|
+
opacity: 1;
|
|
559
|
+
pointer-events: auto;
|
|
560
|
+
}
|
|
561
|
+
.chat-msg-action {
|
|
562
|
+
appearance: none;
|
|
563
|
+
border: 0;
|
|
564
|
+
background: transparent;
|
|
565
|
+
color: var(--fg-2);
|
|
566
|
+
display: inline-flex;
|
|
567
|
+
align-items: center;
|
|
568
|
+
justify-content: center;
|
|
569
|
+
width: 22px;
|
|
570
|
+
height: 22px;
|
|
571
|
+
border-radius: var(--radius-xs);
|
|
572
|
+
cursor: pointer;
|
|
573
|
+
}
|
|
574
|
+
.chat-msg-action:hover {
|
|
575
|
+
background: var(--bg-3);
|
|
576
|
+
color: var(--fg-0);
|
|
577
|
+
}
|
|
578
|
+
.chat-msg-action:disabled {
|
|
579
|
+
opacity: 0.4;
|
|
580
|
+
cursor: default;
|
|
581
|
+
}
|
|
582
|
+
.chat-msg-action[data-copied='true'] {
|
|
583
|
+
color: var(--status-success);
|
|
584
|
+
}
|
|
585
|
+
@media (prefers-reduced-motion: reduce) {
|
|
586
|
+
.chat-msg-actions {
|
|
587
|
+
transition: none;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
460
591
|
/* Rendered markdown inside the assistant bubble (chat-markdown.jsx) */
|
|
461
592
|
.chat-msg--assistant .chat-bubble > * + * {
|
|
462
593
|
margin-top: var(--space-2);
|
|
@@ -553,7 +684,79 @@
|
|
|
553
684
|
white-space: pre-wrap;
|
|
554
685
|
}
|
|
555
686
|
|
|
556
|
-
/*
|
|
687
|
+
/* Collapsed consecutive-tool-call group (Task C1) — mirrors .chat-think's
|
|
688
|
+
<details>/<summary> disclosure pattern exactly. */
|
|
689
|
+
.chat-toolgroup {
|
|
690
|
+
border: 1px solid var(--border-default);
|
|
691
|
+
border-radius: var(--radius-sm);
|
|
692
|
+
background: var(--bg-2);
|
|
693
|
+
overflow: hidden;
|
|
694
|
+
}
|
|
695
|
+
.chat-toolgroup-sum {
|
|
696
|
+
display: flex;
|
|
697
|
+
align-items: center;
|
|
698
|
+
gap: var(--space-2);
|
|
699
|
+
padding: var(--space-2) var(--space-3);
|
|
700
|
+
font-family: var(--font-mono);
|
|
701
|
+
font-size: var(--type-xs);
|
|
702
|
+
color: var(--fg-1);
|
|
703
|
+
cursor: pointer;
|
|
704
|
+
user-select: none;
|
|
705
|
+
list-style: none;
|
|
706
|
+
}
|
|
707
|
+
.chat-toolgroup-sum::-webkit-details-marker {
|
|
708
|
+
display: none;
|
|
709
|
+
}
|
|
710
|
+
.chat-toolgroup-sum::after {
|
|
711
|
+
content: '▸';
|
|
712
|
+
margin-left: auto;
|
|
713
|
+
color: var(--fg-3);
|
|
714
|
+
transition: transform var(--dur-soft) var(--ease-out);
|
|
715
|
+
}
|
|
716
|
+
.chat-toolgroup[open] .chat-toolgroup-sum::after {
|
|
717
|
+
transform: rotate(90deg);
|
|
718
|
+
}
|
|
719
|
+
.chat-toolgroup[open] .chat-toolgroup-sum {
|
|
720
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
721
|
+
}
|
|
722
|
+
.chat-toolgroup-body {
|
|
723
|
+
display: flex;
|
|
724
|
+
flex-direction: column;
|
|
725
|
+
}
|
|
726
|
+
/* Flat accordion row (Task C1 revision) — a bordered card-in-a-card per
|
|
727
|
+
tool read as "divné" (weird) in dogfooding; a group's individual tool
|
|
728
|
+
calls are now plain rows separated by a hairline, not their own
|
|
729
|
+
`.chat-tool` card, so the whole group stays one lightweight shape. */
|
|
730
|
+
.chat-tool-row {
|
|
731
|
+
padding: var(--space-2) var(--space-3);
|
|
732
|
+
display: flex;
|
|
733
|
+
flex-direction: column;
|
|
734
|
+
gap: var(--space-1);
|
|
735
|
+
}
|
|
736
|
+
.chat-tool-row + .chat-tool-row {
|
|
737
|
+
border-top: 1px solid var(--border-subtle);
|
|
738
|
+
}
|
|
739
|
+
.chat-tool-row-main {
|
|
740
|
+
display: flex;
|
|
741
|
+
align-items: center;
|
|
742
|
+
gap: var(--space-2);
|
|
743
|
+
font-family: var(--font-mono);
|
|
744
|
+
font-size: var(--type-xs);
|
|
745
|
+
color: var(--fg-1);
|
|
746
|
+
}
|
|
747
|
+
.chat-tool-row-main b {
|
|
748
|
+
color: var(--accent);
|
|
749
|
+
font-weight: 600;
|
|
750
|
+
}
|
|
751
|
+
.chat-tool-row-status {
|
|
752
|
+
margin-left: auto;
|
|
753
|
+
color: var(--fg-3);
|
|
754
|
+
}
|
|
755
|
+
.chat-tool-row-status.del {
|
|
756
|
+
color: var(--status-error);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/* Tool-call card (standalone — a lone tool call outside a group). */
|
|
557
760
|
.chat-tool {
|
|
558
761
|
border: 1px solid var(--border-default);
|
|
559
762
|
border-radius: var(--radius-sm);
|
|
@@ -608,6 +811,340 @@
|
|
|
608
811
|
.chat-tool-line.del {
|
|
609
812
|
color: var(--status-error);
|
|
610
813
|
}
|
|
814
|
+
/* Raw args/result preview — Verbose transcript view only (Task C4). */
|
|
815
|
+
.chat-tool-detail {
|
|
816
|
+
margin: 0;
|
|
817
|
+
padding: var(--space-2);
|
|
818
|
+
background: var(--bg-3);
|
|
819
|
+
border: 1px solid var(--border-subtle);
|
|
820
|
+
border-radius: var(--radius-xs);
|
|
821
|
+
color: var(--fg-2);
|
|
822
|
+
font-family: var(--font-mono);
|
|
823
|
+
font-size: var(--type-xs);
|
|
824
|
+
white-space: pre-wrap;
|
|
825
|
+
overflow-wrap: anywhere;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
/* Permission approve/deny card (Milestone B — retires DDR-125 F2's blanket
|
|
829
|
+
auto-approve). Sits between the feed and the composer, one at a time. */
|
|
830
|
+
.chat-perm {
|
|
831
|
+
display: flex;
|
|
832
|
+
flex-direction: column;
|
|
833
|
+
gap: var(--space-2);
|
|
834
|
+
margin: 0 var(--space-4);
|
|
835
|
+
padding: var(--space-3);
|
|
836
|
+
border: 1px solid var(--accent);
|
|
837
|
+
border-radius: var(--radius-sm);
|
|
838
|
+
background: var(--bg-2);
|
|
839
|
+
}
|
|
840
|
+
.chat-perm:focus-visible {
|
|
841
|
+
outline: none;
|
|
842
|
+
}
|
|
843
|
+
.chat-perm-hd {
|
|
844
|
+
display: flex;
|
|
845
|
+
align-items: center;
|
|
846
|
+
gap: var(--space-2);
|
|
847
|
+
font-family: var(--font-mono);
|
|
848
|
+
font-size: var(--type-xs);
|
|
849
|
+
color: var(--fg-1);
|
|
850
|
+
}
|
|
851
|
+
/* SECURITY (ethical-hacker finding) — the title is adapter/model-controlled
|
|
852
|
+
(for Bash, it's the raw shell command) with no length bound; without a
|
|
853
|
+
clamp a crafted/long command could push its dangerous tail off-screen in
|
|
854
|
+
a card whose entire point is "you can see what you're approving". Clamps
|
|
855
|
+
to one legible line; the full string is still reachable via the native
|
|
856
|
+
title-attribute tooltip (see PermissionPrompt.jsx). */
|
|
857
|
+
.chat-perm-hd b {
|
|
858
|
+
display: block;
|
|
859
|
+
min-width: 0;
|
|
860
|
+
flex: 1;
|
|
861
|
+
overflow: hidden;
|
|
862
|
+
text-overflow: ellipsis;
|
|
863
|
+
white-space: nowrap;
|
|
864
|
+
color: var(--accent);
|
|
865
|
+
font-weight: 600;
|
|
866
|
+
}
|
|
867
|
+
.chat-perm-queue {
|
|
868
|
+
flex-shrink: 0;
|
|
869
|
+
color: var(--fg-3);
|
|
870
|
+
font-weight: 400;
|
|
871
|
+
}
|
|
872
|
+
.chat-perm-body {
|
|
873
|
+
margin: 0;
|
|
874
|
+
font-size: var(--type-xs);
|
|
875
|
+
color: var(--fg-2);
|
|
876
|
+
}
|
|
877
|
+
.chat-perm-actions {
|
|
878
|
+
display: flex;
|
|
879
|
+
flex-wrap: wrap;
|
|
880
|
+
gap: var(--space-2);
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
/* Form-elicitation card (feature-acp-ask-user-question — AskUserQuestion +
|
|
884
|
+
generic MCP form input). Same slot + shape as .chat-perm, mutually
|
|
885
|
+
exclusive with it — see the mount site in ChatPanel.jsx. */
|
|
886
|
+
.chat-elicit {
|
|
887
|
+
display: flex;
|
|
888
|
+
flex-direction: column;
|
|
889
|
+
gap: var(--space-3);
|
|
890
|
+
margin: 0 var(--space-4);
|
|
891
|
+
padding: var(--space-3) var(--space-4);
|
|
892
|
+
border: 1px solid var(--border-default);
|
|
893
|
+
border-left: 2px solid var(--accent);
|
|
894
|
+
border-radius: var(--radius-sm);
|
|
895
|
+
background: var(--bg-2);
|
|
896
|
+
}
|
|
897
|
+
.chat-elicit:focus-visible {
|
|
898
|
+
outline: none;
|
|
899
|
+
}
|
|
900
|
+
.chat-elicit-hd {
|
|
901
|
+
display: flex;
|
|
902
|
+
flex-direction: column;
|
|
903
|
+
gap: var(--space-1);
|
|
904
|
+
}
|
|
905
|
+
.chat-elicit-hd b {
|
|
906
|
+
color: var(--fg-0);
|
|
907
|
+
font-size: var(--type-sm);
|
|
908
|
+
font-weight: 600;
|
|
909
|
+
line-height: var(--lh-sm);
|
|
910
|
+
}
|
|
911
|
+
.chat-elicit-meta {
|
|
912
|
+
display: flex;
|
|
913
|
+
align-items: center;
|
|
914
|
+
gap: var(--space-2);
|
|
915
|
+
font-family: var(--font-mono);
|
|
916
|
+
font-size: var(--type-xs);
|
|
917
|
+
color: var(--fg-3);
|
|
918
|
+
}
|
|
919
|
+
.chat-elicit-meta > span + span::before {
|
|
920
|
+
content: '·';
|
|
921
|
+
margin-right: var(--space-2);
|
|
922
|
+
}
|
|
923
|
+
.chat-elicit-question {
|
|
924
|
+
display: flex;
|
|
925
|
+
flex-direction: column;
|
|
926
|
+
gap: var(--space-2);
|
|
927
|
+
margin: 0;
|
|
928
|
+
padding: 0;
|
|
929
|
+
border: none;
|
|
930
|
+
}
|
|
931
|
+
.chat-elicit-question-hd {
|
|
932
|
+
display: flex;
|
|
933
|
+
flex-direction: column;
|
|
934
|
+
gap: var(--space-2);
|
|
935
|
+
padding: 0;
|
|
936
|
+
font-size: var(--type-sm);
|
|
937
|
+
color: var(--fg-0);
|
|
938
|
+
line-height: var(--lh-sm);
|
|
939
|
+
}
|
|
940
|
+
.chat-elicit-question-chip {
|
|
941
|
+
align-self: flex-start;
|
|
942
|
+
padding: 2px var(--space-2);
|
|
943
|
+
border-radius: var(--radius-pill);
|
|
944
|
+
background: var(--bg-3);
|
|
945
|
+
color: var(--accent);
|
|
946
|
+
font-family: var(--font-mono);
|
|
947
|
+
font-size: 10px;
|
|
948
|
+
font-weight: 600;
|
|
949
|
+
text-transform: uppercase;
|
|
950
|
+
letter-spacing: 0.04em;
|
|
951
|
+
}
|
|
952
|
+
.chat-elicit-options {
|
|
953
|
+
display: flex;
|
|
954
|
+
flex-direction: column;
|
|
955
|
+
gap: var(--space-1);
|
|
956
|
+
}
|
|
957
|
+
.chat-elicit-option {
|
|
958
|
+
display: flex;
|
|
959
|
+
align-items: flex-start;
|
|
960
|
+
gap: var(--space-2);
|
|
961
|
+
font-size: var(--type-xs);
|
|
962
|
+
color: var(--fg-1);
|
|
963
|
+
cursor: pointer;
|
|
964
|
+
accent-color: var(--accent);
|
|
965
|
+
}
|
|
966
|
+
/* "Other" rides in the radio group itself (single-select only — see
|
|
967
|
+
ElicitationPrompt.jsx) rather than a separate link below it, so the
|
|
968
|
+
either/or truth (one field, one answer) is visible for free through
|
|
969
|
+
native radio-group exclusivity. Styled as a peer option, not a
|
|
970
|
+
secondary action — no visual demotion, it's a real 4th choice. */
|
|
971
|
+
.chat-elicit-option--other {
|
|
972
|
+
color: var(--fg-2);
|
|
973
|
+
}
|
|
974
|
+
.chat-elicit-custom--inline {
|
|
975
|
+
margin-left: calc(16px + var(--space-2)); /* aligns under the "Other" label, not the radio dot */
|
|
976
|
+
}
|
|
977
|
+
.chat-elicit-option-body {
|
|
978
|
+
display: flex;
|
|
979
|
+
flex-direction: column;
|
|
980
|
+
gap: var(--space-1);
|
|
981
|
+
}
|
|
982
|
+
.chat-elicit-option-desc {
|
|
983
|
+
color: var(--fg-2);
|
|
984
|
+
}
|
|
985
|
+
.chat-elicit-option-preview {
|
|
986
|
+
margin: 0;
|
|
987
|
+
padding: var(--space-1) var(--space-2);
|
|
988
|
+
background: var(--bg-3);
|
|
989
|
+
border: 1px solid var(--border-subtle);
|
|
990
|
+
border-radius: var(--radius-xs);
|
|
991
|
+
color: var(--fg-2);
|
|
992
|
+
font-family: var(--font-mono);
|
|
993
|
+
font-size: var(--type-xs);
|
|
994
|
+
white-space: pre-wrap;
|
|
995
|
+
overflow-wrap: anywhere;
|
|
996
|
+
}
|
|
997
|
+
.chat-elicit-text {
|
|
998
|
+
width: 100%;
|
|
999
|
+
padding: var(--space-1) var(--space-2);
|
|
1000
|
+
background: var(--bg-3);
|
|
1001
|
+
border: 1px solid var(--border-subtle);
|
|
1002
|
+
border-radius: var(--radius-xs);
|
|
1003
|
+
color: var(--fg-0);
|
|
1004
|
+
font-size: var(--type-xs);
|
|
1005
|
+
font-family: inherit;
|
|
1006
|
+
}
|
|
1007
|
+
.chat-elicit-custom-toggle {
|
|
1008
|
+
align-self: flex-start;
|
|
1009
|
+
padding: 0;
|
|
1010
|
+
background: none;
|
|
1011
|
+
border: none;
|
|
1012
|
+
color: var(--accent);
|
|
1013
|
+
font-size: var(--type-xs);
|
|
1014
|
+
cursor: pointer;
|
|
1015
|
+
text-decoration: underline;
|
|
1016
|
+
}
|
|
1017
|
+
.chat-elicit-custom-wrap {
|
|
1018
|
+
display: flex;
|
|
1019
|
+
flex-direction: column;
|
|
1020
|
+
gap: var(--space-1);
|
|
1021
|
+
}
|
|
1022
|
+
.chat-elicit-custom-note {
|
|
1023
|
+
margin: 0;
|
|
1024
|
+
color: var(--fg-2);
|
|
1025
|
+
font-size: var(--type-xs);
|
|
1026
|
+
}
|
|
1027
|
+
/* Credential-shaped question warning (ethical-hacker finding — see
|
|
1028
|
+
acp-elicitation.js's looksLikeSecretRequest). Border/left-accent carries
|
|
1029
|
+
the warning color; TEXT stays on --fg-1 rather than --status-warn
|
|
1030
|
+
directly — that token fails AA contrast at this size (bit the a11y
|
|
1031
|
+
review once already, per DDR-097's file-tree badge fix). */
|
|
1032
|
+
.chat-elicit-secret-warning {
|
|
1033
|
+
margin: 0;
|
|
1034
|
+
padding: var(--space-1) var(--space-2);
|
|
1035
|
+
border: 1px solid var(--status-warn);
|
|
1036
|
+
border-radius: var(--radius-xs);
|
|
1037
|
+
background: color-mix(in oklab, var(--status-warn) 12%, transparent);
|
|
1038
|
+
color: var(--fg-1);
|
|
1039
|
+
font-size: var(--type-xs);
|
|
1040
|
+
}
|
|
1041
|
+
/* SECURITY (ethical-hacker finding) — shown when a question reads as a
|
|
1042
|
+
credential ask; pairs with the masked input in ElicitationPrompt.jsx. */
|
|
1043
|
+
.chat-elicit-secret-warning {
|
|
1044
|
+
margin: 0;
|
|
1045
|
+
color: var(--warn, hsl(38 92% 50%));
|
|
1046
|
+
font-size: var(--type-xs);
|
|
1047
|
+
}
|
|
1048
|
+
.chat-elicit-actions {
|
|
1049
|
+
display: flex;
|
|
1050
|
+
flex-wrap: wrap;
|
|
1051
|
+
align-items: center;
|
|
1052
|
+
gap: var(--space-2);
|
|
1053
|
+
}
|
|
1054
|
+
.chat-elicit-actions-spacer {
|
|
1055
|
+
flex: 1 1 auto;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
/* Connection-problem error card (Task C3) — transient bridge/socket failure,
|
|
1059
|
+
recoverable with a retry. Same slot as .chat-perm (mutually exclusive). */
|
|
1060
|
+
.chat-error-card {
|
|
1061
|
+
display: flex;
|
|
1062
|
+
flex-direction: column;
|
|
1063
|
+
gap: var(--space-2);
|
|
1064
|
+
margin: 0 var(--space-4);
|
|
1065
|
+
padding: var(--space-3);
|
|
1066
|
+
border: 1px solid var(--status-error);
|
|
1067
|
+
border-radius: var(--radius-sm);
|
|
1068
|
+
background: var(--bg-2);
|
|
1069
|
+
}
|
|
1070
|
+
.chat-error-hd {
|
|
1071
|
+
display: flex;
|
|
1072
|
+
align-items: center;
|
|
1073
|
+
gap: var(--space-2);
|
|
1074
|
+
font-family: var(--font-mono);
|
|
1075
|
+
font-size: var(--type-xs);
|
|
1076
|
+
color: var(--status-error);
|
|
1077
|
+
}
|
|
1078
|
+
.chat-error-detail {
|
|
1079
|
+
margin: 0;
|
|
1080
|
+
font-size: var(--type-xs);
|
|
1081
|
+
color: var(--fg-2);
|
|
1082
|
+
}
|
|
1083
|
+
.chat-error-detail--muted {
|
|
1084
|
+
color: var(--fg-3);
|
|
1085
|
+
}
|
|
1086
|
+
.chat-error-actions {
|
|
1087
|
+
display: flex;
|
|
1088
|
+
flex-wrap: wrap;
|
|
1089
|
+
gap: var(--space-2);
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
/* Usage (Milestone D) — context-window bar, rendered inside .chat-foot-popover. */
|
|
1093
|
+
.chat-usage-bar {
|
|
1094
|
+
display: inline-block;
|
|
1095
|
+
width: 32px;
|
|
1096
|
+
height: 4px;
|
|
1097
|
+
border-radius: var(--radius-pill);
|
|
1098
|
+
background: var(--bg-4, var(--bg-3));
|
|
1099
|
+
overflow: hidden;
|
|
1100
|
+
flex-shrink: 0;
|
|
1101
|
+
}
|
|
1102
|
+
.chat-usage-bar-fill {
|
|
1103
|
+
display: block;
|
|
1104
|
+
height: 100%;
|
|
1105
|
+
background: var(--accent);
|
|
1106
|
+
border-radius: var(--radius-pill);
|
|
1107
|
+
}
|
|
1108
|
+
/* Full-width variant for the .chat-foot-popover context section (the
|
|
1109
|
+
32px pill above is sized for an inline ambient indicator, not a form
|
|
1110
|
+
bar). */
|
|
1111
|
+
.chat-usage-bar--wide {
|
|
1112
|
+
display: block;
|
|
1113
|
+
width: 100%;
|
|
1114
|
+
height: 5px;
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
/* Event-driven single-window rate-limit banner — rendered INSIDE
|
|
1118
|
+
.chat-composer's own padding (unlike .chat-perm/.chat-error-card, which
|
|
1119
|
+
are siblings of the composer at the thread-root level), so no extra
|
|
1120
|
+
horizontal margin here. */
|
|
1121
|
+
.chat-usage-banner {
|
|
1122
|
+
display: flex;
|
|
1123
|
+
align-items: center;
|
|
1124
|
+
gap: var(--space-2);
|
|
1125
|
+
margin: 0 0 var(--space-3);
|
|
1126
|
+
padding: var(--space-2) var(--space-3);
|
|
1127
|
+
border: 1px solid var(--border-default);
|
|
1128
|
+
border-radius: var(--radius-sm);
|
|
1129
|
+
background: var(--bg-2);
|
|
1130
|
+
color: var(--fg-1);
|
|
1131
|
+
font-size: var(--type-xs);
|
|
1132
|
+
}
|
|
1133
|
+
.chat-usage-banner-x {
|
|
1134
|
+
margin-left: auto;
|
|
1135
|
+
flex-shrink: 0;
|
|
1136
|
+
appearance: none;
|
|
1137
|
+
border: 0;
|
|
1138
|
+
background: transparent;
|
|
1139
|
+
color: var(--fg-3);
|
|
1140
|
+
cursor: pointer;
|
|
1141
|
+
font-size: var(--type-sm);
|
|
1142
|
+
line-height: 1;
|
|
1143
|
+
padding: 0 var(--space-1);
|
|
1144
|
+
}
|
|
1145
|
+
.chat-usage-banner-x:hover {
|
|
1146
|
+
color: var(--fg-0);
|
|
1147
|
+
}
|
|
611
1148
|
|
|
612
1149
|
/* Quick-action row */
|
|
613
1150
|
.chat-quick {
|
|
@@ -712,7 +1249,30 @@
|
|
|
712
1249
|
.chat-toolbar-spacer {
|
|
713
1250
|
flex: 1;
|
|
714
1251
|
}
|
|
715
|
-
/*
|
|
1252
|
+
/* Model/effort/mode picker row (feature-acp-panel-dynamic-claude-code-
|
|
1253
|
+
capabilities) — a flex row of .chat-select dropdowns inside .chat-toolbar. */
|
|
1254
|
+
.chat-caps {
|
|
1255
|
+
display: flex;
|
|
1256
|
+
align-items: center;
|
|
1257
|
+
gap: var(--space-1);
|
|
1258
|
+
flex-wrap: wrap;
|
|
1259
|
+
}
|
|
1260
|
+
.chat-caps--connecting {
|
|
1261
|
+
font-family: var(--font-body);
|
|
1262
|
+
font-size: var(--type-xs);
|
|
1263
|
+
color: var(--fg-3);
|
|
1264
|
+
padding: 2px var(--space-2);
|
|
1265
|
+
}
|
|
1266
|
+
/* Compact toolbar dropdowns — borderless, hover-revealed (Zed-style).
|
|
1267
|
+
Without `field-sizing`, a closed <select> sizes itself to its WIDEST
|
|
1268
|
+
option (not the one it's currently showing) — Model ends up as wide as
|
|
1269
|
+
its longest model name even while displaying "Sonnet". That's what made
|
|
1270
|
+
2-3 short picks unable to share a row in a narrow panel — each one was
|
|
1271
|
+
wider than it looked and forced onto its own wrapped line. `field-sizing:
|
|
1272
|
+
content` sizes it to what's actually shown instead; it degrades
|
|
1273
|
+
harmlessly where unsupported (the max-width + ellipsis below is that
|
|
1274
|
+
fallback net), and `flex-shrink: 0` keeps the (now much smaller) content
|
|
1275
|
+
width from being squeezed further by the toolbar row. */
|
|
716
1276
|
.chat-select {
|
|
717
1277
|
appearance: none;
|
|
718
1278
|
font-family: var(--font-body);
|
|
@@ -723,6 +1283,13 @@
|
|
|
723
1283
|
border-radius: var(--radius-xs);
|
|
724
1284
|
padding: 2px var(--space-2);
|
|
725
1285
|
cursor: pointer;
|
|
1286
|
+
flex-shrink: 0;
|
|
1287
|
+
field-sizing: content;
|
|
1288
|
+
min-width: 44px;
|
|
1289
|
+
max-width: 140px;
|
|
1290
|
+
overflow: hidden;
|
|
1291
|
+
text-overflow: ellipsis;
|
|
1292
|
+
white-space: nowrap;
|
|
726
1293
|
transition:
|
|
727
1294
|
border-color var(--dur-soft) var(--ease-out),
|
|
728
1295
|
background var(--dur-soft) var(--ease-out),
|
|
@@ -795,16 +1362,86 @@
|
|
|
795
1362
|
color: var(--fg-2);
|
|
796
1363
|
font-family: var(--font-mono);
|
|
797
1364
|
}
|
|
798
|
-
.chat-foot {
|
|
1365
|
+
.chat-foot-spacer {
|
|
1366
|
+
flex: 1;
|
|
1367
|
+
}
|
|
1368
|
+
/* Composer footer info (Milestone D, revised twice after dogfooding — the
|
|
1369
|
+
keyboard hint + context gauge + mode footnote + subscription note first
|
|
1370
|
+
collapsed behind an icon on its own row, then that icon moved INTO
|
|
1371
|
+
.chat-toolbar next to Send so it costs no extra vertical space). The
|
|
1372
|
+
popover is grouped into labeled sections (context / cost / mode /
|
|
1373
|
+
meta) with dividers, rather than a flat stack of unrelated lines. */
|
|
1374
|
+
.chat-foot-info {
|
|
1375
|
+
position: relative;
|
|
1376
|
+
display: inline-flex;
|
|
1377
|
+
}
|
|
1378
|
+
.chat-foot-info-btn {
|
|
1379
|
+
appearance: none;
|
|
1380
|
+
border: 0;
|
|
1381
|
+
background: transparent;
|
|
1382
|
+
cursor: pointer;
|
|
1383
|
+
color: var(--fg-3);
|
|
1384
|
+
font-size: var(--type-sm);
|
|
1385
|
+
line-height: 1;
|
|
1386
|
+
padding: 2px var(--space-1);
|
|
1387
|
+
border-radius: var(--radius-xs);
|
|
1388
|
+
}
|
|
1389
|
+
.chat-foot-info-btn:hover,
|
|
1390
|
+
.chat-foot-info-btn[aria-expanded='true'] {
|
|
1391
|
+
color: var(--fg-1);
|
|
1392
|
+
background: var(--bg-3);
|
|
1393
|
+
}
|
|
1394
|
+
.chat-foot-info-btn:focus-visible {
|
|
1395
|
+
outline: none;
|
|
1396
|
+
border-color: var(--accent);
|
|
1397
|
+
box-shadow: 0 0 0 3px var(--accent-tint);
|
|
1398
|
+
}
|
|
1399
|
+
/* `position: fixed` (not absolute) — `.chat-foot-info` sits inside
|
|
1400
|
+
`.chat-box`, which clips its content with `overflow: hidden` for the
|
|
1401
|
+
composer's rounded-corner focus ring. An absolutely-positioned popover
|
|
1402
|
+
anchored there got clipped to that box instead of floating above the
|
|
1403
|
+
whole composer. `bottom`/`right` are computed from the button's own
|
|
1404
|
+
rect and set inline (see ChatFootInfo in ChatPanel.jsx). */
|
|
1405
|
+
.chat-foot-popover {
|
|
1406
|
+
position: fixed;
|
|
1407
|
+
z-index: 52;
|
|
799
1408
|
display: flex;
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
1409
|
+
flex-direction: column;
|
|
1410
|
+
min-width: 240px;
|
|
1411
|
+
padding: var(--space-3);
|
|
1412
|
+
background: var(--bg-2);
|
|
1413
|
+
border: 1px solid var(--border-default);
|
|
1414
|
+
border-radius: var(--radius-sm);
|
|
1415
|
+
box-shadow: var(--shadow-lg);
|
|
1416
|
+
font-family: var(--font-mono);
|
|
803
1417
|
font-size: var(--type-xs);
|
|
804
1418
|
color: var(--fg-2);
|
|
805
1419
|
}
|
|
806
|
-
.chat-foot-
|
|
807
|
-
|
|
1420
|
+
.chat-foot-popover-section {
|
|
1421
|
+
display: flex;
|
|
1422
|
+
flex-direction: column;
|
|
1423
|
+
gap: 6px;
|
|
1424
|
+
}
|
|
1425
|
+
.chat-foot-popover-sep {
|
|
1426
|
+
height: 1px;
|
|
1427
|
+
background: var(--border-subtle);
|
|
1428
|
+
margin: var(--space-2) calc(var(--space-3) * -1);
|
|
1429
|
+
}
|
|
1430
|
+
.chat-foot-popover-label-row {
|
|
1431
|
+
display: flex;
|
|
1432
|
+
align-items: center;
|
|
1433
|
+
justify-content: space-between;
|
|
1434
|
+
gap: var(--space-2);
|
|
1435
|
+
color: var(--fg-0);
|
|
1436
|
+
font-weight: 600;
|
|
1437
|
+
}
|
|
1438
|
+
.chat-foot-popover-row--muted {
|
|
1439
|
+
color: var(--fg-3);
|
|
1440
|
+
}
|
|
1441
|
+
.chat-foot-popover-foot {
|
|
1442
|
+
display: flex;
|
|
1443
|
+
flex-direction: column;
|
|
1444
|
+
gap: 4px;
|
|
808
1445
|
}
|
|
809
1446
|
|
|
810
1447
|
/* ── Slash-command autocomplete + inline highlight ────────────────────────
|