@xenosystem/agent-interface-ui 0.1.51 → 0.1.68

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 (2) hide show
  1. package/dist/agent.css +181 -20
  2. package/package.json +7 -7
package/dist/agent.css CHANGED
@@ -45,9 +45,17 @@
45
45
  --xeno-hover: rgba(169, 169, 177, 0.08);
46
46
  --xeno-text: #d8d8de;
47
47
  --xeno-muted: #7f7f86;
48
+ /* secondary READING text (hints, meta, captions) — AA on every panel surface; `--xeno-muted` is the
49
+ resting state of an interactive label and is 3.46:1 on a control well, so it is not for prose */
50
+ --xeno-muted-text: #9a9aa1;
48
51
  --xeno-active: #acacb4;
49
52
  --xeno-danger: #ef4444;
50
53
  --xeno-danger-hover: #dc2626;
54
+ /* status as TEXT — the fill hues fail AA as small text; one lighter tone per meaning */
55
+ --xeno-danger-text: #f27a7a;
56
+ --xeno-success-text: #6fae7f;
57
+ --xeno-warning-text: #c98d2a;
58
+ --xeno-info-text: #7aa2c4;
51
59
  --xeno-on-accent: #08080a;
52
60
 
53
61
  /* scrollbar — its own alphas on purpose. A thumb sitting on any surface in the set has to be legible
@@ -102,8 +110,13 @@
102
110
  --xeno-hover: rgba(0, 0, 0, 0.05);
103
111
  --xeno-text: #1a1815;
104
112
  --xeno-muted: #6f6b64;
113
+ --xeno-muted-text: #5f5b55;
105
114
  --xeno-active: #3a3833;
106
115
  --xeno-on-accent: #faf9f7;
116
+ --xeno-danger-text: #b42318;
117
+ --xeno-success-text: #1a6b32;
118
+ --xeno-warning-text: #7a4f00;
119
+ --xeno-info-text: #2a5f8a;
107
120
  --xeno-scroll-rail: rgba(0, 0, 0, 0.08);
108
121
  --xeno-scroll-thumb: rgba(0, 0, 0, 0.18);
109
122
  --xeno-scroll-thumb-hover: rgba(0, 0, 0, 0.32);
@@ -226,7 +239,7 @@
226
239
  --xeno-chrome-panel-header-min-h: 34px;
227
240
  --xeno-chrome-panel-body-pad: 12px;
228
241
  --xeno-chrome-title-size: 11px;
229
- --xeno-chrome-title-color: var(--xeno-muted);
242
+ --xeno-chrome-title-color: var(--xeno-muted-text);
230
243
  --xeno-chrome-title-transform: uppercase;
231
244
  --xeno-chrome-title-spacing: 0.08em;
232
245
  --xeno-chrome-dialog-header-pad: 6px 12px;
@@ -2832,7 +2845,7 @@
2832
2845
  var(--xeno-control);
2833
2846
  }
2834
2847
  .xeno-btn[data-variant='ghost'] {
2835
- color: var(--xeno-muted);
2848
+ color: var(--xeno-muted-text);
2836
2849
  }
2837
2850
  .xeno-btn[data-variant='ghost']:hover:not(:disabled) {
2838
2851
  color: var(--xeno-text);
@@ -3240,7 +3253,7 @@
3240
3253
  margin-top: 11px;
3241
3254
  padding-top: 11px;
3242
3255
  border-top: var(--xeno-chrome-divider);
3243
- color: var(--xeno-muted);
3256
+ color: var(--xeno-muted-text);
3244
3257
  font-size: 13px;
3245
3258
  line-height: 1.3;
3246
3259
  }
@@ -3393,6 +3406,11 @@
3393
3406
  border-bottom-left-radius: var(--xeno-chrome-radius-plate);
3394
3407
  border-bottom-right-radius: var(--xeno-chrome-radius-plate);
3395
3408
  }
3409
+
3410
+ .xeno-panel-body:focus-visible {
3411
+ outline: 1px solid var(--xeno-text);
3412
+ outline-offset: -1px;
3413
+ }
3396
3414
  /*
3397
3415
  * Chip — a small selectable/removable token. SQUARE (radius-control), 1px hairline border, monochrome
3398
3416
  * shell. State is driven by `data-*` on the root; size metrics arrive as inline `--xeno-h/-padx/-gap/
@@ -3759,7 +3777,7 @@
3759
3777
  border: 1px solid var(--xeno-border);
3760
3778
  border-radius: var(--xeno-radius-xs);
3761
3779
  background: var(--xeno-control);
3762
- color: var(--xeno-muted);
3780
+ color: var(--xeno-muted-text);
3763
3781
  overflow: hidden;
3764
3782
  user-select: none;
3765
3783
  vertical-align: middle;
@@ -3781,13 +3799,13 @@
3781
3799
  font-weight: 600;
3782
3800
  line-height: 1;
3783
3801
  letter-spacing: 0.02em;
3784
- color: var(--xeno-muted);
3802
+ color: var(--xeno-muted-text);
3785
3803
  text-transform: uppercase;
3786
3804
  }
3787
3805
 
3788
3806
  /* Glyph fallback inherits the tile's muted ink via currentColor. */
3789
3807
  .xeno-avatar[data-variant='icon'] {
3790
- color: var(--xeno-muted);
3808
+ color: var(--xeno-muted-text);
3791
3809
  }
3792
3810
 
3793
3811
  /* ── AvatarStack ─────────────────────────────────────────────────────────────────── */
@@ -5898,7 +5916,7 @@ a.xeno-source-card:focus-visible {
5898
5916
  .xeno-sources-chevron {
5899
5917
  display: inline-flex;
5900
5918
  flex: none;
5901
- color: var(--xeno-muted);
5919
+ color: var(--xeno-muted-text);
5902
5920
  transform: rotate(-90deg);
5903
5921
  transition: transform var(--xeno-dur) var(--xeno-ease);
5904
5922
  }
@@ -5930,7 +5948,7 @@ a.xeno-source-card:focus-visible {
5930
5948
  background: var(--xeno-control);
5931
5949
  border: 1px solid var(--xeno-surface);
5932
5950
  border-radius: var(--xeno-radius-sm);
5933
- color: var(--xeno-muted);
5951
+ color: var(--xeno-muted-text);
5934
5952
  font-size: 10px;
5935
5953
  font-weight: 600;
5936
5954
  line-height: 1;
@@ -5946,14 +5964,14 @@ a.xeno-source-card:focus-visible {
5946
5964
  object-fit: cover;
5947
5965
  }
5948
5966
  .xeno-sources-overflow {
5949
- color: var(--xeno-muted);
5967
+ color: var(--xeno-muted-text);
5950
5968
  font-size: 9px;
5951
5969
  }
5952
5970
 
5953
5971
  /* Count — mono, muted, pushed to the far end. */
5954
5972
  .xeno-sources-count {
5955
5973
  margin-left: auto;
5956
- color: var(--xeno-muted);
5974
+ color: var(--xeno-muted-text);
5957
5975
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
5958
5976
  font-size: 12px;
5959
5977
  font-variant-numeric: tabular-nums;
@@ -7660,23 +7678,161 @@ a.xeno-source-card:focus-visible {
7660
7678
  .xa-line .xa-cur .xa-t.xa-first { animation: xa-slidein 280ms var(--xa-ease) both; animation-delay: 120ms; }
7661
7679
  .xa-line .xa-cur .xa-t.xa-in { animation: xa-slidein 260ms var(--xa-ease) both; animation-delay: 90ms; }
7662
7680
  .xa-line .xa-cur .xa-t.xa-out { animation: xa-blurout 160ms var(--xa-ease-out) both; }
7663
- .xa-collapsed .xa-turn.xa-live:not(.xa-open):not(.xa-done) .xa-line .xa-vr { display: block; }
7664
- .xa-collapsed .xa-turn.xa-live:not(.xa-open):not(.xa-done) .xa-line .xa-cur { display: flex; }
7681
+ /* the divider is a separator between two occupied regions. A live turn with nothing
7682
+ on the right (plain "Working for 1s", no thought, no step) must not keep a dangling
7683
+ │ — `.xa-t` is the ticker's words, so :has(.xa-t) is "there is something to the right". */
7684
+ .xa-collapsed .xa-turn.xa-live:not(.xa-open):not(.xa-done) .xa-line:has(.xa-t) .xa-vr { display: block; }
7685
+ .xa-collapsed .xa-turn.xa-live:not(.xa-open):not(.xa-done) .xa-line:has(.xa-t) .xa-cur { display: flex; }
7686
+ /* thought-only: Thought/Thinking STAYS on the clock when the line opens. The live rule above
7687
+ hides the ticker on `.xa-open` so a click used to drop a second Thought row under Working for. */
7688
+ .xa-collapsed .xa-turn.xa-thought-only .xa-line:has(.xa-t) .xa-vr { display: block; }
7689
+ .xa-collapsed .xa-turn.xa-thought-only .xa-line:has(.xa-t) .xa-cur { display: flex; }
7665
7690
  /* ONE settled step rides the line where the live ticker had it — the receipt IS the step, not a
7666
7691
  count for it (2026-09-19). The rail underneath still opens: the thought and the step's own
7667
7692
  detail live there, left-aligned under the clock as always. The ask rule above still wins: a
7668
7693
  settled turn cannot be asking (asking is live), so these only ever apply to a receipt. */
7669
7694
  .xa-collapsed .xa-turn.xa-done .xa-line.xa-docked .xa-vr { display: block; }
7670
7695
  .xa-collapsed .xa-turn.xa-done .xa-line.xa-docked .xa-cur { display: flex; }
7671
- /* thought-only receipt: "Thought" is on the clock line, so the rail is the reasoning — no second
7672
- header, no icon column, no rail stem. The turn's own fold still hides this until the line opens. */
7673
- .xa-collapsed .xa-turn.xa-done .xa-row.xa-think.xa-docked .xa-ic,
7674
- .xa-collapsed .xa-turn.xa-done .xa-row.xa-think.xa-docked .xa-head { display: none; }
7675
- .xa-collapsed .xa-turn.xa-done .xa-row.xa-think.xa-docked::before { display: none; }
7676
- .xa-collapsed .xa-turn.xa-done .xa-row.xa-think.xa-docked .xa-fullwrap {
7677
- grid-template-rows: 1fr;
7678
- margin: 0 0 2px;
7696
+ /* thought-only ticker is a short word (Thinking / Thought). The line's mask fades the last
7697
+ 44px of .xa-cur — on a hugging column that is the WHOLE word, so it vanished (2026-09-20).
7698
+ Words are in-flow so the auto column sizes to them; the slot is optional (gone when settled). */
7699
+ .xa-collapsed .xa-turn.xa-thought-only .xa-line .xa-cur {
7700
+ flex: none;
7701
+ min-width: min-content;
7702
+ overflow: visible;
7703
+ mask-image: none;
7704
+ -webkit-mask-image: none;
7705
+ }
7706
+ .xa-collapsed .xa-turn.xa-thought-only .xa-line .xa-cur .xa-tx {
7707
+ flex: none;
7708
+ min-width: min-content;
7709
+ overflow: visible;
7710
+ height: auto;
7711
+ }
7712
+ .xa-collapsed .xa-turn.xa-thought-only .xa-line .xa-cur .xa-t { position: static; }
7713
+ /* thought-only: one grid live AND settled. Leftover width sits in shots, not in Thought,
7714
+ so `Worked for 2s | Thought ›` hugs the bar and the hang (cur+chev+shots) never
7715
+ changes tracks when xa-live comes off. */
7716
+ .xa-collapsed .xa-turn.xa-thought-only .xa-line.xa-thought {
7717
+ display: grid;
7718
+ grid-template-columns: auto auto auto auto auto 1fr;
7719
+ /* The clock row is PINNED to the line's own height (22px), never `auto`. With `auto 0fr` the
7720
+ first track absorbed the leftover height of the folded second one, so it measured 22px shut
7721
+ and 16px open — the words jumped UP 3px the instant the trace opened, then back on close.
7722
+ A fixed first track means opening cannot move the clock line at all; only row two grows.
7723
+ The hang's `0fr -> 1fr` is TRANSITIONED, as the bench does it (`.xrow.think .fullwrap`:
7724
+ `grid-template-rows 220ms`), so the trace unrolls instead of snapping (measured 2026-09-20). */
7725
+ grid-template-rows: var(--xa-clockrow, 22px) auto;
7726
+ grid-template-areas:
7727
+ "dot read vr cur chev shots"
7728
+ ". . . hang hang hang";
7729
+ column-gap: 10px;
7730
+ row-gap: 0;
7731
+ align-items: center;
7732
+ }
7733
+ /* settled: the square is display:none, but an empty first track still takes column-gap.
7734
+ Drop the `dot` column so Worked for sits on the left with no indent. Hang stays on Thought. */
7735
+ .xa-collapsed .xa-turn.xa-thought-only:not(.xa-live) .xa-line.xa-thought {
7736
+ grid-template-columns: auto auto auto auto 1fr;
7737
+ grid-template-areas:
7738
+ "read vr cur chev shots"
7739
+ ". . hang hang hang";
7740
+ }
7741
+ /* THINKING WAS THE WHOLE TURN: `Worked for 2s | Thought for 2s` is one fact said twice, so the
7742
+ wrapper falls away and the thought takes the line — `Thought for 2s >`. Only when the two
7743
+ durations READ the same (see the JSX); the moment there is other work the receipt returns.
7744
+ `Worked for` blurs out exactly as the square does, and the thought glides into its place:
7745
+ the same fold, one column further. */
7746
+ /* RUN-IN: the trace begins on the SAME line, just right of `Thought for 2s >`, and wraps to the
7747
+ full width underneath — so a one-sentence trace reads as one line rather than a header with a
7748
+ near-empty row under it. A float is the only thing that does this: grid and flex both put a
7749
+ child in its OWN track, which is what produced the second row. The header floats, the trace is
7750
+ ordinary flow text, and the browser shortens the first line by the float's width for free.
7751
+ The line stops being a grid here, so the `grid-area` assignments below no longer apply to it. */
7752
+ .xa-collapsed .xa-turn.xa-thought-only:not(.xa-live) .xa-line.xa-thoughtsolo {
7753
+ display: block;
7754
+ }
7755
+ /* 🔴 The float's HEIGHT decides how many lines are shortened. At the clock row's 22px it
7756
+ overlapped the trace's second 16px line too, so line 1 also started at x=91.6 instead of
7757
+ returning to the left margin — measured. Matching the float to the text's own line-height
7758
+ means exactly ONE line runs in, and every line after it is full width. */
7759
+ .xa-collapsed .xa-turn.xa-thought-only:not(.xa-live) .xa-line.xa-thoughtsolo > .xa-cur,
7760
+ .xa-collapsed .xa-turn.xa-thought-only:not(.xa-live) .xa-line.xa-thoughtsolo > .xa-chev {
7761
+ float: left;
7762
+ height: 16px;
7763
+ display: flex;
7764
+ align-items: center;
7765
+ }
7766
+ .xa-collapsed .xa-turn.xa-thought-only:not(.xa-live) .xa-line.xa-thoughtsolo > .xa-chev {
7767
+ margin-right: 8px; /* the gap the grid's column-gap used to give */
7768
+ }
7769
+ /* 🔴 The trace must NOT establish a block formatting context. `overflow: hidden` does, and a BFC
7770
+ never overlaps a float — measured, the whole block indented to x=91.6 and sat beside the header
7771
+ instead of wrapping under it. The fold's `overflow: hidden` therefore cannot live here; the
7772
+ 0fr/1fr grid on `.xa-hang` is also a BFC, so the FOLD moves out to a wrapper and this element
7773
+ stays plain flow text. */
7774
+ .xa-collapsed .xa-turn.xa-thought-only:not(.xa-live) .xa-line.xa-thoughtsolo > .xa-hang {
7775
+ display: block;
7776
+ overflow: visible;
7777
+ grid-template-rows: none;
7778
+ transition: none;
7779
+ }
7780
+ .xa-collapsed .xa-turn.xa-thought-only:not(.xa-live) .xa-line.xa-thoughtsolo > .xa-hang > .xa-hangin {
7781
+ overflow: visible;
7782
+ padding: 0;
7783
+ }
7784
+ /* folded: the trace is simply not rendered, rather than a zero-height box that would still
7785
+ shorten the first line */
7786
+ .xa-collapsed .xa-turn.xa-thought-only:not(.xa-open) .xa-line.xa-thoughtsolo > .xa-hang { display: none; }
7787
+ .xa-collapsed .xa-turn.xa-thought-only:not(.xa-live) .xa-line.xa-thoughtsolo > .xa-shots { float: right; }
7788
+ /* the float must not escape the line into the reply below it */
7789
+ .xa-collapsed .xa-turn.xa-thought-only:not(.xa-live) .xa-line.xa-thoughtsolo::after {
7790
+ content: '';
7791
+ display: block;
7792
+ clear: both;
7793
+ }
7794
+ .xa-collapsed .xa-turn.xa-thought-only .xa-line.xa-thoughtsolo > .xa-read,
7795
+ .xa-collapsed .xa-turn.xa-thought-only .xa-line.xa-thoughtsolo > .xa-vr { display: none; }
7796
+ .xa-turn.xa-settle .xa-line.xa-thoughtsolo .xa-read { animation: xa-dotout 200ms var(--xa-ease-out) both; }
7797
+ .xa-collapsed .xa-turn.xa-thought-only .xa-line.xa-thought > .xa-dot { grid-area: dot; }
7798
+ .xa-collapsed .xa-turn.xa-thought-only .xa-line.xa-thought > .xa-read { grid-area: read; }
7799
+ .xa-collapsed .xa-turn.xa-thought-only .xa-line.xa-thought > .xa-vr { grid-area: vr; }
7800
+ .xa-collapsed .xa-turn.xa-thought-only .xa-line.xa-thought > .xa-cur { grid-area: cur; }
7801
+ .xa-collapsed .xa-turn.xa-thought-only .xa-line.xa-thought > .xa-chev { grid-area: chev; }
7802
+ .xa-collapsed .xa-turn.xa-thought-only .xa-line.xa-thought > .xa-shots { grid-area: shots; }
7803
+ /* the line sets `align-items: center`, which applies to the hang too: in the folded `0fr` track it
7804
+ sized to its own 16px and CENTRED, so the trace hung 8px BELOW the clock line while collapsed —
7805
+ a stray line of reasoning under a folded turn (measured 2026-09-20). Stretching it makes the
7806
+ track's height its height, so 0fr really is nothing. */
7807
+ .xa-collapsed .xa-turn.xa-thought-only .xa-line.xa-thought > .xa-hang {
7808
+ grid-area: hang;
7809
+ align-self: stretch;
7810
+ display: grid;
7811
+ grid-template-rows: 0fr;
7812
+ min-width: 0;
7813
+ min-height: 0;
7814
+ transition: grid-template-rows 220ms var(--xa-ease);
7815
+ }
7816
+ .xa-collapsed .xa-turn.xa-thought-only.xa-open .xa-line.xa-thought > .xa-hang { grid-template-rows: 1fr; }
7817
+ .xa-collapsed .xa-turn.xa-thought-only .xa-line.xa-thought > .xa-hang > .xa-hangin {
7818
+ min-height: 0;
7819
+ overflow: hidden;
7820
+ /* the padding is part of the open box, so it must travel WITH the row or it lands in one
7821
+ frame while the row is still unrolling — an 8px step at the start of a 220ms move
7822
+ (measured). The bench transitions its wrapper's margin for the same reason. */
7823
+ transition: padding 220ms var(--xa-ease);
7824
+ padding: 6px 0 2px;
7825
+ font-size: 11.5px;
7826
+ line-height: 16px;
7827
+ color: var(--xa-t4);
7828
+ }
7829
+ .xa-collapsed .xa-turn.xa-thought-only:not(.xa-open) .xa-line.xa-thought > .xa-hang > .xa-hangin { padding: 0; }
7830
+ @media (prefers-reduced-motion: reduce) {
7831
+ .xa-collapsed .xa-turn.xa-thought-only .xa-line.xa-thought > .xa-hang,
7832
+ .xa-collapsed .xa-turn.xa-thought-only .xa-line.xa-thought > .xa-hang > .xa-hangin { transition: none; }
7679
7833
  }
7834
+ .xa-collapsed .xa-turn.xa-thought-only .xa-hang p { margin: 0 0 4px; }
7835
+ .xa-collapsed .xa-turn.xa-thought-only .xa-hang p:last-child { margin: 0; }
7680
7836
  .xa-collapsed .xa-turn.xa-live:not(.xa-open):not(.xa-asking) .xa-railwrap { grid-template-rows: 0fr; }
7681
7837
  /* an ask surfaces alone: its row and its card, the rest of the rail stays folded */
7682
7838
  .xa-collapsed .xa-turn.xa-live.xa-asking:not(.xa-open) .xa-rail .xa-row:not(.xa-ask):not(.xa-sub),
@@ -7688,6 +7844,11 @@ a.xeno-source-card:focus-visible {
7688
7844
  .xa-collapsed .xa-turn.xa-live .xa-line { cursor: pointer; }
7689
7845
  .xa-collapsed .xa-turn.xa-live.xa-asking:not(.xa-open) .xa-rail .xa-row.xa-sub { display: flex; }
7690
7846
  .xa-collapsed .xa-turn.xa-live.xa-asking:not(.xa-open) .xa-rail .xa-row.xa-sub.xa-folded { display: none; }
7847
+ /* a docked thought with no recorded words: the duration is real, the trace is not — so the
7848
+ line says `Thought for 4s` and offers no chevron to open nothing (2026-09-20) */
7849
+ .xa-line.xa-inert .xa-chev { display: none; }
7850
+ .xa-turn:not(.xa-live) .xa-line.xa-inert { cursor: default; }
7851
+ .xa-turn:not(.xa-live) .xa-line.xa-inert:hover .xa-read { color: var(--xa-t4); }
7691
7852
  .xa-line .xa-shots { margin-left: auto; display: flex; gap: 4px; }
7692
7853
  .xa-railwrap { display: grid; grid-template-rows: 1fr; transition: grid-template-rows 220ms var(--xa-ease); }
7693
7854
  .xa-turn:not(.xa-live):not(.xa-open) .xa-railwrap { grid-template-rows: 0fr; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xenosystem/agent-interface-ui",
3
- "version": "0.1.51",
3
+ "version": "0.1.68",
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -33,7 +33,7 @@
33
33
  "directory": "packages/ui"
34
34
  },
35
35
  "dependencies": {
36
- "@xenosystem/elements-react": "0.0.1",
36
+ "@xenosystem/elements-react": "0.0.5",
37
37
  "@xterm/addon-fit": "^0.11.0",
38
38
  "@xterm/xterm": "^6.0.0",
39
39
  "clsx": "^2.1.1",
@@ -42,11 +42,11 @@
42
42
  "react-markdown": "^10.1.0",
43
43
  "remark-gfm": "^4.0.1",
44
44
  "zustand": "^5.0.2",
45
- "@xenosystem/agent-interface-client": "0.1.51",
46
- "@xenosystem/agent-conversation": "0.1.51",
47
- "@xenosystem/agent-interface-core": "0.1.51",
48
- "@xenosystem/agent-interface-hub-adapter": "0.1.51",
49
- "@xenosystem/agent-interface-contract": "0.1.51"
45
+ "@xenosystem/agent-conversation": "0.1.68",
46
+ "@xenosystem/agent-interface-client": "0.1.68",
47
+ "@xenosystem/agent-interface-contract": "0.1.68",
48
+ "@xenosystem/agent-interface-hub-adapter": "0.1.68",
49
+ "@xenosystem/agent-interface-core": "0.1.68"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "react": "^19.0.0",