@bivy/bivy 0.17.1-staging.12 → 0.17.1-staging.3

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.
@@ -169,8 +169,6 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
169
169
  .badge[data-variant="soft"][data-tone="ok"] { background: color-mix(in srgb, var(--ok) 16%, var(--surface)); color: var(--ok); }
170
170
  .badge[data-variant="soft"][data-tone="warn"] { background: var(--warn-soft); color: var(--warn); }
171
171
  .badge[data-variant="soft"][data-tone="danger"] { background: var(--danger-soft); color: var(--danger); }
172
- .badge[data-variant="soft"][data-tone="merged"] { background: color-mix(in srgb, var(--merged) 16%, var(--surface)); color: var(--merged); }
173
- .badge[data-variant="soft"]:not([data-tone]) { background: var(--surface-3); color: var(--muted); }
174
172
  .badge[data-variant="solid"] { border-color: transparent; color: var(--accent-contrast); }
175
173
  .badge[data-variant="solid"][data-tone="accent"] { background: var(--accent); }
176
174
  .badge[data-variant="solid"][data-tone="ok"] { background: var(--ok); }
@@ -213,39 +211,29 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
213
211
  }
214
212
  .sidebar-head {
215
213
  display: flex; align-items: center; justify-content: space-between;
216
- min-height: 56px; padding: var(--space-2) var(--space-2) var(--space-1) var(--space-4);
214
+ padding: 14px 16px; border-bottom: 1px solid var(--line);
217
215
  /* As a fixed drawer on mobile the sidebar starts at the very top of the
218
216
  screen, so its header must clear the status bar / notch the same way the
219
- main .topbar does — otherwise the wordmark sits under the clock. */
220
- padding-top: max(var(--space-2), env(safe-area-inset-top));
217
+ main .topbar does — otherwise "Bivy" and "+ New" sit under the clock. */
218
+ padding-top: max(14px, env(safe-area-inset-top));
221
219
  }
222
- .sidebar-head-actions { display: flex; align-items: center; gap: var(--space-2); }
223
- .brand { font-family: var(--font-serif); font-weight: 500; font-size: var(--text-xl); letter-spacing: 0; }
220
+ .sidebar-head-actions { display: flex; align-items: center; gap: 8px; }
221
+ .brand { font-family: var(--font-serif); font-weight: 500; font-size: 17px; letter-spacing: 0; }
224
222
  /* Primary destinations sit above the session stream. Keeping Automations here
225
223
  makes it discoverable without competing with the quieter Settings footer. */
226
- .sidebar-nav { display: flex; flex-direction: column; gap: 2px; padding: 0 0 var(--space-3); }
224
+ .sidebar-nav { padding: var(--space-2) 0 var(--space-3); }
227
225
  .sidebar-nav-item {
228
- display: flex; align-items: center; gap: var(--space-3); width: 100%; min-height: 40px;
229
- padding: var(--space-2); border: 0; border-radius: var(--radius-md);
230
- background: transparent; color: var(--ink); font: inherit; font-size: var(--text-md); font-weight: var(--weight-normal);
226
+ display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px;
227
+ padding: 9px 10px; border: 0; border-radius: var(--radius-sm);
228
+ background: transparent; color: var(--ink); font: inherit; font-size: var(--text-sm); font-weight: var(--weight-medium);
231
229
  text-align: left; cursor: pointer; transition: color var(--dur) var(--ease-standard), background var(--dur) var(--ease-standard);
232
230
  }
233
- .sidebar-nav-item svg { color: var(--ink); flex: none; }
234
- .sidebar-nav-item:hover:not(:disabled) { background: var(--surface-2); }
235
- .sidebar-nav-item:disabled { opacity: 0.45; cursor: default; }
236
- .sidebar-nav-item.active { background: var(--surface-2); }
237
- /* Foot: the single primary action (New session) + the Settings gear. No rule
238
- above it — the list simply scrolls underneath. */
239
- .sidebar-foot {
240
- margin-top: auto; display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
241
- padding: var(--space-3) var(--space-3) max(var(--space-3), env(safe-area-inset-bottom));
242
- background: var(--surface);
243
- }
244
- .btn.new-session-btn {
245
- display: inline-flex; align-items: center; gap: var(--space-2); min-height: 44px;
246
- padding: 0 var(--space-5) 0 var(--space-4); border-radius: var(--radius-full);
247
- font-size: var(--text-md); font-weight: var(--weight-semibold);
248
- }
231
+ .sidebar-nav-item svg { color: var(--accent); flex: none; }
232
+ .sidebar-nav-item:hover { background: var(--surface-2); }
233
+ .sidebar-nav-item.active { background: transparent; color: var(--accent); }
234
+ .sidebar-nav-item.active:hover { background: var(--surface-2); }
235
+ .sidebar-nav-chevron { margin-left: auto; color: var(--muted); font-size: var(--text-xl); font-weight: var(--weight-normal); line-height: 1; }
236
+ .sidebar-foot { margin-top: auto; padding: var(--space-2); border-top: 1px solid var(--line); display: flex; flex-direction: column; gap: var(--space-1); }
249
237
  /* Red dot on the mobile ☰ burger when something needs the user that they
250
238
  haven't seen (an agent blocked on approval/question, an unseen finished run,
251
239
  a provider needing auth). Replaces the old separate inbox surface — the
@@ -293,18 +281,15 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
293
281
  .session-list { display: flex; flex-direction: column; min-height: 0; flex: 1; overflow-y: auto; overflow-x: hidden; padding: 8px; }
294
282
  .session-list-heading { display: flex; align-items: baseline; justify-content: space-between; padding: var(--space-3) var(--space-2) var(--space-2); color: var(--ink); font-size: var(--text-md); font-weight: var(--weight-semibold); }
295
283
  .session-list-count { color: var(--muted); font-size: var(--text-xs); font-weight: var(--weight-normal); font-variant-numeric: tabular-nums; }
296
- /* Search (the canonical .field, with a leading glyph) + a quiet filter icon. */
297
- .session-list-tools { display: flex; align-items: center; gap: var(--space-1); margin-bottom: var(--space-2); }
298
- .session-search-wrap { position: relative; flex: 1; min-width: 0; display: flex; color: var(--muted); }
299
- .session-search-wrap > svg { position: absolute; left: var(--space-3); top: 50%; transform: translateY(-50%); pointer-events: none; }
300
- .session-search { flex: 1; min-width: 0; padding-left: calc(var(--space-3) + 17px + var(--space-2)); }
284
+ .session-list-tools { display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2); }
285
+ .session-search { flex: 1; min-width: 0; }
301
286
  .session-filter { position: relative; flex: none; }
302
287
  .session-filter-btn {
303
288
  position: relative; display: inline-flex; align-items: center; justify-content: center;
304
- width: 32px; height: 32px; border: 0; border-radius: var(--radius-full);
305
- background: transparent; color: var(--muted); font-size: 20px; line-height: 1;
289
+ width: 38px; height: 38px; border: 1px solid var(--line); border-radius: var(--radius-md);
290
+ background: var(--surface-2); color: var(--muted); font-size: 20px; line-height: 1;
306
291
  }
307
- .session-filter-btn:hover, .session-filter-btn.active, .session-filter-btn[aria-expanded="true"] { color: var(--ink); background: var(--surface-3); }
292
+ .session-filter-btn:hover, .session-filter-btn.active, .session-filter-btn[aria-expanded="true"] { color: var(--ink); border-color: var(--line-strong); background: var(--surface-3); }
308
293
  .session-filter-count { position: absolute; right: -5px; top: -5px; min-width: 17px; height: 17px; padding: 0 var(--space-1); }
309
294
  .session-filter-menu {
310
295
  position: absolute; right: 0; top: calc(100% + 6px); width: min(280px, calc(100vw - 24px)); z-index: var(--z-dropdown);
@@ -320,30 +305,36 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
320
305
  .session-filter-clear { flex: none; border: 0; background: transparent; color: var(--accent); padding: 2px 0; font-size: 12px; }
321
306
  .session-list ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
322
307
  .session-group-label {
323
- padding: var(--space-4) var(--space-2) var(--space-1); color: var(--muted);
324
- font-size: var(--text-xs); line-height: var(--lh-xs); font-weight: var(--weight-semibold);
308
+ padding: 12px 8px 4px; color: var(--muted); font-size: 11px; line-height: 1.2;
309
+ font-weight: 650; letter-spacing: 0.02em;
325
310
  }
326
- .session-group-label:first-child { padding-top: var(--space-2); }
311
+ .session-group-label:first-child { padding-top: 6px; }
327
312
  .session-item {
328
- position: relative; display: flex; align-items: center; gap: var(--space-2); width: 100%; text-align: left;
329
- padding: var(--space-2); border: 0; border-radius: var(--radius-md); background: transparent; color: var(--ink);
313
+ position: relative; display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
314
+ padding: 9px 8px; border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--ink);
330
315
  }
331
316
  .session-item:hover { background: var(--surface-2); }
332
- .session-item.active, .session-item[aria-current="page"] { background: var(--surface-2); }
333
- /* Two single-line rows: title (+ status dot, PR mark, age) over a quiet meta
334
- line. A dot appears only for states that want attention (see RowMark). */
317
+ .session-item.active, .session-item[aria-current="page"] {
318
+ background: var(--surface-2);
319
+ }
320
+ .session-item.active::before, .session-item[aria-current="page"]::before {
321
+ content: ""; position: absolute; inset: 0 auto 0 0; width: 2px;
322
+ background: var(--accent);
323
+ }
324
+ /* Column wrapper for the two-line row (title row + meta row) so the dot can
325
+ stay a single flex sibling, vertically centered across both lines. */
335
326
  .session-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
336
- .session-title-row { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
337
- .row-status { flex: none; display: inline-flex; }
327
+ .session-title-row { display: flex; align-items: flex-start; gap: 6px; min-width: 0; }
338
328
  .session-name {
339
- flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
340
- font-size: var(--text-base); line-height: var(--lh-base); font-weight: var(--weight-medium);
329
+ flex: 1; min-width: 0; overflow: hidden; font-size: 13px; font-weight: 600; line-height: 1.25;
330
+ display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
341
331
  }
342
332
  /* Relative age, pinned to the row's trailing edge; flex:none so it never
343
333
  shrinks or forces the row to scroll sideways. */
344
- .session-age { flex: none; font-size: var(--text-xs); color: var(--muted); font-variant-numeric: tabular-nums; line-height: var(--lh-xs); }
345
- /* Agent / repo / branch descriptor line, below the title. */
346
- .session-meta { font-size: var(--text-xs); line-height: var(--lh-xs); color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
334
+ .session-age { flex: none; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; line-height: 1.25; }
335
+ /* Agent / node / branch descriptor line, below the title. Slightly larger than
336
+ before: 11px muted text was the main source of an illegible sidebar. */
337
+ .session-meta { font-size: 12px; line-height: 1.25; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
347
338
  @keyframes dot-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.6; } }
348
339
  .session-row { position: relative; display: flex; align-items: center; }
349
340
  .session-row .session-item { flex: 1; min-width: 0; }
@@ -405,12 +396,6 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
405
396
  the composer no longer moves it. margin-bottom stays auto so a tall pane keeps
406
397
  it in the upper-middle rather than pinned hard to the top. */
407
398
  .chat-empty { margin: calc(var(--app-h, 100dvh) * 0.22) auto auto; color: var(--muted); max-width: 320px; padding: 0 20px; text-align: center; }
408
- .chat-greeting { margin: auto; padding: var(--space-6) var(--space-4); text-align: center; }
409
- .chat-greeting h2 {
410
- margin: 0; font-family: var(--font-serif); font-weight: var(--weight-normal);
411
- font-size: var(--text-3xl); line-height: var(--lh-3xl); color: var(--ink); text-wrap: balance;
412
- }
413
- @media (max-width: 720px) { .chat-greeting h2 { font-size: var(--text-2xl); line-height: var(--lh-2xl); } }
414
399
  .chat-empty-title { margin: 0 0 6px; font-size: 16px; font-weight: 600; color: var(--ink); }
415
400
  .chat-empty-sub { margin: 0; font-size: 13px; line-height: 1.5; }
416
401
  .chat-empty-sub b { color: var(--ink); font-weight: 600; }
@@ -586,27 +571,19 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
586
571
  discoverability pattern as .row-menu-btn — and a touch-friendly baseline
587
572
  opacity on devices with no hover. */
588
573
  .assistant-row { align-self: stretch; width: 100%; max-width: 680px; }
589
- .msg-actions { display: flex; align-items: center; gap: 2px; margin-top: var(--space-1); margin-left: -6px; }
574
+ .msg-actions { display: flex; align-items: center; gap: 2px; margin-top: 4px; }
590
575
  .msg-copy-btn, .msg-speak-btn {
591
576
  border: 0; background: transparent; color: var(--muted);
592
577
  display: inline-flex; align-items: center; justify-content: center;
593
- width: 32px; height: 32px; padding: 0; border-radius: var(--radius-sm);
594
- cursor: pointer; transition: opacity var(--dur-fast) ease, color var(--dur-fast) ease;
578
+ width: 26px; height: 26px; padding: 0; border-radius: var(--radius-sm); opacity: 0.35;
579
+ cursor: pointer; transition: opacity 0.12s ease, color 0.12s ease;
595
580
  }
581
+ .assistant-row:hover .msg-copy-btn, .assistant-row:hover .msg-speak-btn,
582
+ .msg-copy-btn:focus-visible, .msg-speak-btn:focus-visible { opacity: 1; }
596
583
  .msg-copy-btn:hover, .msg-speak-btn:hover { background: var(--surface-2); color: var(--ink); }
597
- .msg-copy-btn.copied { color: var(--ok); }
598
- .msg-speak-btn.speaking { color: var(--accent); }
599
- /* Actions belong to the answer: only a turn's final reply carries them. An
600
- interim reply ("Let me look at…") drops them on touch, and on a wide pointer
601
- screen keeps them one hover (or Tab) away in the column's right gutter. */
602
- .turn-response-body > .assistant-row:has(~ .assistant-row) > .msg-actions { display: none; }
603
- @media (hover: hover) and (min-width: 1100px) {
604
- .turn-response-body > .assistant-row:has(~ .assistant-row) { position: relative; }
605
- .turn-response-body > .assistant-row:has(~ .assistant-row) > .msg-actions {
606
- display: flex; position: absolute; top: 0; left: 100%; margin: 0 0 0 var(--space-2); opacity: 0;
607
- }
608
- .turn-response-body > .assistant-row:has(~ .assistant-row):is(:hover, :focus-within) > .msg-actions { opacity: 1; }
609
- }
584
+ .msg-copy-btn.copied { color: var(--ok); opacity: 1; }
585
+ .msg-speak-btn.speaking { color: var(--accent); opacity: 1; }
586
+ @media (hover: none) { .msg-copy-btn, .msg-speak-btn { opacity: 0.6; } }
610
587
 
611
588
  /* ---- Tool activity (grouped summary line -> bottom sheet detail + diff) ---- */
612
589
  .tool-group { align-self: stretch; width: 100%; max-width: 680px; }
@@ -734,13 +711,14 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
734
711
  .github-pill .gh-icon { width: 14px; height: 14px; }
735
712
  .github-pill .gh-text { max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
736
713
 
737
- /* Compact PR mark (open/merged/closed): a soft tinted chip whose glyph shape
738
- names the state, plus a count when there's more than one. Non-interactive —
739
- it sits inside a row/pill <button>. */
740
- .session-pr { flex: none; gap: 3px; padding: 0 var(--space-1); height: 18px; font-size: 11px; line-height: 1; font-variant-numeric: tabular-nums; }
741
- .session-pr:not(:has(.session-pr-text)) { width: 18px; padding: 0; justify-content: center; }
742
- .session-pr .pr-glyph { width: 12px; height: 12px; flex: none; }
743
- .session-pr-text { white-space: nowrap; font-weight: var(--weight-semibold); }
714
+ /* Compact PR badge on a sidebar row (open/merged/closed), colour-matched to the
715
+ header pill. Non-interactive — it sits inside the row's <button>. */
716
+ .session-pr { flex: none; gap: 3px; padding: 0 6px; height: 16px; font-size: 10px; line-height: 1; letter-spacing: 0.02em; }
717
+ .session-pr .gh-icon { width: 10px; height: 10px; }
718
+ /* The label is all-caps with no descenders, so within the line box its ink
719
+ rides above the optical centre and reads high in the fixed-height pill. Nudge
720
+ it down a touch to sit on the pill's true centre next to the glyph. */
721
+ .session-pr-text { white-space: nowrap; position: relative; top: 0.5px; }
744
722
 
745
723
  /* ---- Source marks & run pill (see sessionSource.ts / SourceMark.tsx) ----
746
724
  Source identity is carried by the glyph alone: every mark renders a quiet
@@ -768,9 +746,6 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
768
746
  .source-mark svg { width: 17px; height: 17px; display: block; }
769
747
  .source-mark.sm { width: 22px; height: 22px; border-radius: var(--radius-sm); }
770
748
  .source-mark.sm svg { width: 13px; height: 13px; }
771
- /* Inline in a row's meta line, sized to the text. */
772
- .source-mark.xs { width: 16px; height: 16px; border-radius: calc(var(--radius-sm) / 2); margin-right: var(--space-1); vertical-align: -3px; }
773
- .source-mark.xs svg { width: 10px; height: 10px; }
774
749
  .source-mark.has-status { position: relative; }
775
750
  .source-mark.has-status .status-dot {
776
751
  position: absolute; right: -3px; bottom: -3px;
@@ -782,20 +757,26 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
782
757
  /* In-session run pill (App.tsx composer band): supersedes the GitHub pill for a
783
758
  triggered session. Source glyph + short label + a status segment. */
784
759
  .run-pill {
785
- display: inline-flex; align-items: center; gap: var(--space-2); flex: 0 1 auto; min-width: 0; min-height: 32px;
786
- border: 0; background: var(--surface-2); color: var(--ink);
787
- border-radius: var(--radius-full); padding: var(--space-1) var(--space-3);
788
- font-size: var(--text-sm); font-weight: var(--weight-medium);
760
+ display: inline-flex; align-items: center; gap: 7px; flex: 0 1 auto; min-width: 0;
761
+ border: 1px solid var(--line); background: var(--surface-2); color: var(--ink);
762
+ border-radius: var(--radius-full); padding: 4px 11px 4px 5px; font-size: 12px; font-weight: 600;
789
763
  }
790
- .run-pill:has(> .source-mark) { padding-left: var(--space-1); }
791
- .run-pill:hover { background: var(--surface-3); }
764
+ .run-pill:hover { border-color: var(--line-strong); background: var(--surface-3); }
792
765
  .run-pill-label { flex: none; }
793
766
  .run-pill-stat {
794
- display: inline-flex; align-items: center; gap: 6px; min-width: 0; color: var(--muted);
767
+ display: inline-flex; align-items: center; gap: 5px; min-width: 0;
768
+ padding-left: 8px; border-left: 1px solid var(--line); color: var(--muted);
795
769
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
796
770
  }
797
771
  /* Session-level file edit count — replaces the bulky ChangesCard above the composer. */
798
- .run-pill-files { flex: none; color: var(--muted); white-space: nowrap; }
772
+ .run-pill-files {
773
+ flex: none;
774
+ padding-left: 8px;
775
+ border-left: 1px solid var(--line);
776
+ color: var(--muted);
777
+ font-weight: 600;
778
+ white-space: nowrap;
779
+ }
799
780
  .run-pill.working .run-pill-stat { color: var(--accent); }
800
781
  .run-pill.needs-action .run-pill-stat, .run-pill.failed .run-pill-stat { color: var(--danger); }
801
782
 
@@ -819,10 +800,9 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
819
800
  /* Run-pill sheet outcome: the run evidence (checks, attempts, duration,
820
801
  branch/commit, agent) joined from the account queue — see runEvidence.ts. */
821
802
  .run-sheet-failure { padding: 11px 16px; border-bottom: 1px solid var(--line); color: var(--danger); font-size: 13px; line-height: 1.4; }
822
- /* Key/value facts read as one quiet group: no rule between rows, one rule
823
- between groups (and before the action rows that follow). */
824
- .run-sheet-rows { display: flex; flex-direction: column; padding: var(--space-2) 0; border-bottom: 1px solid var(--line); }
825
- .run-sheet-row { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); padding: 6px var(--space-4); font-size: var(--text-sm); }
803
+ .run-sheet-rows { display: flex; flex-direction: column; }
804
+ .run-sheet-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 9px 16px; border-bottom: 1px solid var(--line); font-size: 13px; }
805
+ .run-sheet-row:last-child { border-bottom: 0; }
826
806
  .run-sheet-row .k { flex: none; color: var(--muted); }
827
807
  .run-sheet-row .v { min-width: 0; display: flex; flex-wrap: wrap; gap: 4px 8px; justify-content: flex-end; align-items: center; color: var(--ink); font-weight: 600; text-align: right; }
828
808
  .run-sheet-row code { font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; padding: 1px 5px; border-radius: var(--radius-sm); border: 1px solid var(--line); background: var(--surface-2); }
@@ -856,10 +836,7 @@ button.sheet-action:last-child { border-bottom: 0; }
856
836
  /* GitHub pills parked in a band just above the composer: the repo picker on a
857
837
  draft (.composer-lead) and the issue/PR context pill on an active session
858
838
  (.composer-gh). .composer-gh collapses out of flow when there's no context. */
859
- /* The band and the composer share the transcript's centred column, so on a wide
860
- screen the input sits under the conversation rather than spanning the pane. */
861
- .composer-gh, .composer-lead, .composer { align-self: center; width: min(100%, 800px); box-sizing: border-box; }
862
- .composer-gh, .composer-lead { display: flex; padding: var(--space-2) var(--space-3) 0; }
839
+ .composer-gh, .composer-lead { display: flex; padding: 8px 10px 0; }
863
840
  .composer-gh { align-items: center; gap: 6px; }
864
841
  /* The draft lead row carries more than one pick (repo + sandbox), so space them
865
842
  and let them wrap on a narrow phone instead of squashing. */
@@ -885,14 +862,14 @@ button.sheet-action:last-child { border-bottom: 0; }
885
862
 
886
863
  /* ---- Composer ---- */
887
864
  .composer {
888
- display: flex; padding: var(--space-2) var(--space-3);
889
- padding-bottom: max(var(--space-2), env(safe-area-inset-bottom));
865
+ display: flex; padding: 8px 10px;
866
+ padding-bottom: max(8px, env(safe-area-inset-bottom));
890
867
  }
891
868
  .composer-card {
892
869
  position: relative;
893
- flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--space-1);
894
- border: 1px solid var(--line); border-radius: var(--radius-xl); background: var(--surface-2);
895
- padding: var(--space-2) var(--space-2) var(--space-2) var(--space-4);
870
+ flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px;
871
+ border: 1px solid var(--line-strong); border-radius: var(--radius-md); background: var(--surface-2);
872
+ padding: 8px 8px 8px 12px;
896
873
  }
897
874
  /* Slash-command autocomplete: a popover floating just above the composer. */
898
875
  .slash-menu {
@@ -903,7 +880,7 @@ button.sheet-action:last-child { border-bottom: 0; }
903
880
  .slash-empty { padding: 10px 12px; color: var(--muted); font-size: 13px; }
904
881
  .slash-name { font-weight: 600; font-size: 14px; flex: none; min-width: 74px; }
905
882
  .slash-desc { color: var(--muted); font-size: 13px; }
906
- .composer-card:focus-within { border-color: var(--accent); }
883
+ .composer-card:focus-within { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
907
884
  /* Keep two readable lines even when autosize runs inside the hidden onboarding shell. */
908
885
  .composer-input {
909
886
  min-height: calc(2 * var(--lh-lg) + 2 * var(--space-1)); flex-shrink: 0;
@@ -919,12 +896,11 @@ button.sheet-action:last-child { border-bottom: 0; }
919
896
  flex: 1; min-width: 0; display: flex; align-items: center; gap: 6px; overflow: hidden;
920
897
  }
921
898
  .composer-meta > .btn {
922
- gap: 6px; min-width: 0; flex: 0 1 auto; color: var(--muted); font-weight: var(--weight-medium);
899
+ gap: var(--space-1); min-width: 0; flex: 0 1 auto; color: var(--ink);
923
900
  }
924
- .composer-meta > .btn:hover { color: var(--ink); }
925
901
  /* Keep the startup action readable beside a long agent name on phones. */
926
902
  .composer-meta:has([data-pending-model]) { flex-wrap: wrap; }
927
- .pill-glyph { color: inherit; flex: none; display: inline-flex; align-items: center; }
903
+ .pill-glyph { color: var(--accent); flex: none; display: inline-flex; align-items: center; }
928
904
  .pill-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
929
905
  /* Glyph-only / short controls keep their natural width; only the long
930
906
  agent + model labels give way when space is tight. */
@@ -938,9 +914,7 @@ button.sheet-action:last-child { border-bottom: 0; }
938
914
  .composer-btn.send:not(:disabled):hover { background: var(--accent-hover); }
939
915
  .composer-btn.send:not(:disabled):active { transform: scale(0.92); }
940
916
  .composer-btn.send:disabled { opacity: 0.35; cursor: default; }
941
- /* Stop is a neutral, high-contrast square — the most important control while a
942
- turn runs, without borrowing the danger colour for an ordinary action. */
943
- .composer-btn.stop { background: var(--ink); color: var(--bg); }
917
+ .composer-btn.stop { background: var(--danger); color: var(--danger-contrast); }
944
918
  .composer-btn.stop.is-stopping { width: auto; border-radius: var(--radius-full); padding-inline: var(--space-3); display: inline-flex; gap: var(--space-2); }
945
919
  .composer-btn.stop:active { transform: scale(0.92); }
946
920
  /* "Steer current turn": an explicit interrupt, distinct from the default Send
@@ -953,7 +927,7 @@ button.sheet-action:last-child { border-bottom: 0; }
953
927
  .attach-pill { padding: 4px 8px; }
954
928
 
955
929
  /* Voice-input trigger: a circular icon button seated just left of Send. */
956
- .composer-btn.mic { background: transparent; color: var(--muted); }
930
+ .composer-btn.mic { background: var(--surface-3); color: var(--muted); }
957
931
  .composer-btn.mic:not(:disabled):hover { color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, var(--surface-3)); }
958
932
  .composer-btn.mic:not(:disabled):active { transform: scale(0.92); }
959
933
  .composer-btn.mic:disabled { opacity: 0.4; cursor: default; }
@@ -2219,13 +2193,6 @@ a.queue-item:hover { border-color: var(--line-strong); background: var(--surface
2219
2193
  /* Keep both selected values visible. Long agent/model names share the
2220
2194
  available row and use the composer's standard ellipsis behavior. */
2221
2195
  .composer-meta { gap: 2px; }
2222
- /* Phone width can't hold both full names beside two 44px buttons: the
2223
- (already compacted) model keeps its label, the agent name gives way first,
2224
- and the agent's decorative glyph goes so its name keeps more letters. */
2225
- .composer-meta > .btn { padding-inline: 6px; }
2226
- .composer-meta > .model-pill { flex-shrink: 0; max-width: 50%; }
2227
- .agent-pill .pill-glyph { display: none; }
2228
- .composer-actions { gap: var(--space-1); }
2229
2196
  .automations-view-head { align-items: center; padding-bottom: 8px; }
2230
2197
  .automations-view-head-text { min-width: 0; }
2231
2198
  .automations-view-sub { display: none; }
@@ -2662,13 +2629,15 @@ textarea.picker-search { resize: vertical; font-family: ui-monospace, monospace;
2662
2629
  .btn.lg { padding: 11px 18px; font-size: var(--text-md); }
2663
2630
  .btn.icon { padding: var(--space-1); min-width: var(--space-7); min-height: var(--space-7); font-size: var(--text-xl); line-height: 1; }
2664
2631
  .btn[aria-busy="true"] { cursor: wait; }
2665
- /* ---- Sidebar settings gear (round companion to New session, ChatGPT-style) ---- */
2666
- .btn.icon.settings-gear {
2667
- display: inline-flex; align-items: center; justify-content: center; flex: none;
2668
- width: 44px; height: 44px; padding: 0; border: 0; border-radius: var(--radius-full);
2669
- background: var(--surface-2); color: var(--ink);
2670
- }
2671
- .btn.icon.settings-gear:hover { background: var(--surface-3); }
2632
+ /* ---- Sidebar settings gear (single entry point, ChatGPT-style) ---- */
2633
+ .settings-gear {
2634
+ display: inline-flex; align-items: center; justify-content: flex-start; gap: 10px; position: relative;
2635
+ width: 100%; border: 0; background: transparent; color: var(--ink);
2636
+ border-radius: var(--radius-sm); padding: 9px 10px; min-height: 40px; font-size: 13px; font-weight: 550;
2637
+ }
2638
+ .settings-gear:hover { background: var(--surface-2); }
2639
+ .settings-gear svg { flex: none; color: var(--muted); }
2640
+ .settings-gear:hover svg { color: var(--ink); }
2672
2641
 
2673
2642
  /* ---- Usage bar ---- */
2674
2643
 
@@ -12,9 +12,8 @@
12
12
  * hex or px. `pnpm run check:design` enforces that no other stylesheet redeclares
13
13
  * a palette token. See packages/web/CLAUDE.md for the design rules agents follow.
14
14
  *
15
- * Palette: high-contrast light + dark themes whose neutrals carry a faint cool
16
- * tint (the accent's hue) so surfaces and the accent read as one family; dark
17
- * sits on true black. Color is reserved for actions and status. Toggle dark with <html data-theme="dark">; with no attribute it
15
+ * Palette: high-contrast neutral light + dark themes, with color reserved for
16
+ * actions and status. Toggle dark with <html data-theme="dark">; with no attribute it
18
17
  * follows the OS. prefers-reduced-motion collapses the motion tokens.
19
18
  *
20
19
  * Naming: the canonical vocabulary is --bg / --surface* / --ink / --muted /
@@ -30,12 +29,12 @@
30
29
  /* ---- Core surfaces & text (neutral) ---- */
31
30
  --bg: #ffffff;
32
31
  --surface: #ffffff;
33
- --surface-2: #f3f5f7;
34
- --surface-3: #e8ecef;
35
- --ink: #0f1215;
36
- --muted: #5f6a73;
37
- --line: #e3e7ea;
38
- --line-strong: #cdd4d9;
32
+ --surface-2: #f5f5f5;
33
+ --surface-3: #ededed;
34
+ --ink: #111111;
35
+ --muted: #6b6b6b;
36
+ --line: #e5e5e5;
37
+ --line-strong: #d4d4d4;
39
38
  --overlay: rgba(0, 0, 0, 0.46);
40
39
  --overlay-strong: rgba(0, 0, 0, 0.8);
41
40
 
@@ -157,8 +156,8 @@
157
156
 
158
157
  :root[data-theme="dark"] {
159
158
  color-scheme: dark;
160
- --bg: #000000; --surface: #000000; --surface-2: #15181b; --surface-3: #22272b;
161
- --ink: #f3f5f7; --muted: #99a2aa; --line: #1f2327; --line-strong: #353b41;
159
+ --bg: #0a0a0a; --surface: #0a0a0a; --surface-2: #171717; --surface-3: #262626;
160
+ --ink: #fafafa; --muted: #a3a3a3; --line: #262626; --line-strong: #404040;
162
161
  --overlay: rgba(0, 0, 0, 0.7); --overlay-strong: rgba(0, 0, 0, 0.8);
163
162
  --accent: #8fb6cd; --accent-contrast: #0a0a0a; --accent-hover: #a7cadd;
164
163
  --danger: #c08a83; --danger-soft: #3a2420; --danger-contrast: #0a0a0a; --ok: #86a99f; --merged: #a99bc4;
@@ -179,8 +178,8 @@
179
178
  @media (prefers-color-scheme: dark) {
180
179
  :root:not([data-theme]) {
181
180
  color-scheme: dark;
182
- --bg: #000000; --surface: #000000; --surface-2: #15181b; --surface-3: #22272b;
183
- --ink: #f3f5f7; --muted: #99a2aa; --line: #1f2327; --line-strong: #353b41;
181
+ --bg: #0a0a0a; --surface: #0a0a0a; --surface-2: #171717; --surface-3: #262626;
182
+ --ink: #fafafa; --muted: #a3a3a3; --line: #262626; --line-strong: #404040;
184
183
  --overlay: rgba(0, 0, 0, 0.7); --overlay-strong: rgba(0, 0, 0, 0.8);
185
184
  --accent: #8fb6cd; --accent-contrast: #0a0a0a; --accent-hover: #a7cadd;
186
185
  --danger: #c08a83; --danger-soft: #3a2420; --danger-contrast: #0a0a0a; --ok: #86a99f; --merged: #a99bc4;
@@ -71,14 +71,6 @@ export function messageContentAtoms(message) {
71
71
  }
72
72
  else if (type === "text")
73
73
  pushText(b.text);
74
- // Reasoning is an atom too: Claude streams each thinking block as its own
75
- // assistant message, and without this a reloaded thinking-only message had
76
- // no atoms, read as "opaque", and was re-appended after the final answer.
77
- else if (type === "thinking" || type === "reasoning") {
78
- const text = thinkingTextFromContent([b]).trim();
79
- if (text)
80
- texts.push(`thinking#${text}`);
81
- }
82
74
  }
83
75
  }
84
76
  return { toolIds, texts };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bivy/bivy",
3
- "version": "0.17.1-staging.12",
3
+ "version": "0.17.1-staging.3",
4
4
  "type": "module",
5
5
  "license": "AGPL-3.0-only",
6
6
  "description": "Run coding agents on machines you own. Open-source, self-hostable agent workspace.",