@oddessentials/agent-guild 0.4.0 → 0.6.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 (91) hide show
  1. package/README.md +13 -8
  2. package/bin/agent-guild-report.mjs +14 -1
  3. package/bin/agent-guild.mjs +85 -46
  4. package/config/providers.default.json +4 -0
  5. package/package.json +1 -1
  6. package/src/manager/changelog.mjs +195 -0
  7. package/src/manager/launch.mjs +64 -0
  8. package/src/manager/main.mjs +27 -4
  9. package/src/manager/news.mjs +5 -5
  10. package/src/manager/providers.mjs +11 -0
  11. package/src/manager/server.mjs +52 -16
  12. package/src/manager/session-history.mjs +496 -0
  13. package/src/manager/session-manager.mjs +4 -0
  14. package/src/manager/session.mjs +16 -0
  15. package/src/report/hooks.mjs +4 -0
  16. package/web/app.js +754 -56
  17. package/web/art/art.css +372 -159
  18. package/web/art/characters/anthropic/idle.avif +0 -0
  19. package/web/art/characters/anthropic/idle.webp +0 -0
  20. package/web/art/characters/anthropic/locked.avif +0 -0
  21. package/web/art/characters/anthropic/locked.webp +0 -0
  22. package/web/art/characters/anthropic/working.avif +0 -0
  23. package/web/art/characters/anthropic/working.webp +0 -0
  24. package/web/art/characters/google/idle.avif +0 -0
  25. package/web/art/characters/google/idle.webp +0 -0
  26. package/web/art/characters/google/locked.avif +0 -0
  27. package/web/art/characters/google/locked.webp +0 -0
  28. package/web/art/characters/google/working.avif +0 -0
  29. package/web/art/characters/google/working.webp +0 -0
  30. package/web/art/characters/openai/idle.avif +0 -0
  31. package/web/art/characters/openai/idle.webp +0 -0
  32. package/web/art/characters/openai/locked.avif +0 -0
  33. package/web/art/characters/openai/locked.webp +0 -0
  34. package/web/art/characters/openai/working.avif +0 -0
  35. package/web/art/characters/openai/working.webp +0 -0
  36. package/web/art/characters/shell/idle.avif +0 -0
  37. package/web/art/characters/shell/idle.webp +0 -0
  38. package/web/art/characters/shell/locked.avif +0 -0
  39. package/web/art/characters/shell/locked.webp +0 -0
  40. package/web/art/characters/shell/working.avif +0 -0
  41. package/web/art/characters/shell/working.webp +0 -0
  42. package/web/art/characters/xai/idle.avif +0 -0
  43. package/web/art/characters/xai/idle.webp +0 -0
  44. package/web/art/characters/xai/locked.avif +0 -0
  45. package/web/art/characters/xai/locked.webp +0 -0
  46. package/web/art/characters/xai/working.avif +0 -0
  47. package/web/art/characters/xai/working.webp +0 -0
  48. package/web/art/icons/anthropic.avif +0 -0
  49. package/web/art/icons/anthropic.webp +0 -0
  50. package/web/art/icons/google.avif +0 -0
  51. package/web/art/icons/google.webp +0 -0
  52. package/web/art/icons/openai.avif +0 -0
  53. package/web/art/icons/openai.webp +0 -0
  54. package/web/art/icons/shell.avif +0 -0
  55. package/web/art/icons/shell.webp +0 -0
  56. package/web/art/icons/xai.avif +0 -0
  57. package/web/art/icons/xai.webp +0 -0
  58. package/web/art/page-light.avif +0 -0
  59. package/web/art/page-light.webp +0 -0
  60. package/web/art/page.avif +0 -0
  61. package/web/art/page.webp +0 -0
  62. package/web/art/ui/empty-state.avif +0 -0
  63. package/web/art/ui/empty-state.webp +0 -0
  64. package/web/art/ui/favicon.png +0 -0
  65. package/web/art/ui/frame-ornate.png +0 -0
  66. package/web/art/ui/guild-crest.png +0 -0
  67. package/web/fonts/OFL.txt +93 -0
  68. package/web/fonts/cinzel.woff2 +0 -0
  69. package/web/index.html +82 -14
  70. package/web/styles.css +208 -68
  71. package/web/art/characters/anthropic/idle.png +0 -0
  72. package/web/art/characters/anthropic/locked.png +0 -0
  73. package/web/art/characters/anthropic/working.png +0 -0
  74. package/web/art/characters/google/idle.png +0 -0
  75. package/web/art/characters/google/locked.png +0 -0
  76. package/web/art/characters/google/working.png +0 -0
  77. package/web/art/characters/openai/idle.png +0 -0
  78. package/web/art/characters/openai/locked.png +0 -0
  79. package/web/art/characters/openai/working.png +0 -0
  80. package/web/art/characters/shell/idle.png +0 -0
  81. package/web/art/characters/shell/locked.png +0 -0
  82. package/web/art/characters/shell/working.png +0 -0
  83. package/web/art/characters/xai/idle.png +0 -0
  84. package/web/art/characters/xai/locked.png +0 -0
  85. package/web/art/characters/xai/working.png +0 -0
  86. package/web/art/icons/anthropic.png +0 -0
  87. package/web/art/icons/google.png +0 -0
  88. package/web/art/icons/openai.png +0 -0
  89. package/web/art/icons/shell.png +0 -0
  90. package/web/art/icons/xai.png +0 -0
  91. package/web/art/page.png +0 -0
package/web/styles.css CHANGED
@@ -1,21 +1,50 @@
1
+ @font-face {
2
+ font-family: "Cinzel";
3
+ src: url("/fonts/cinzel.woff2") format("woff2");
4
+ font-weight: 400 900;
5
+ font-display: swap;
6
+ }
7
+ @font-face {
8
+ font-family: "Cinzel Fallback";
9
+ src: local("Palatino Linotype"), local("Palatino"), local("Georgia");
10
+ ascent-override: 97.6%;
11
+ descent-override: 37.2%;
12
+ line-gap-override: 0%;
13
+ }
14
+
1
15
  :root {
2
- --bg: #f6f7f9;
3
- --surface: #ffffff;
4
- --surface-2: #f0f2f5;
5
- --border: #dde1e7;
6
- --text: #1b1f24;
7
- --muted: #5f6b7a;
8
- --accent: #5b5bd6;
16
+ --bg: #f3eee3;
17
+ --surface: #fffcf6;
18
+ --surface-2: #f5eedf;
19
+ --border: #e3d7bd;
20
+ --text: #221b12;
21
+ --muted: #6b5c45;
22
+ --heading: #2c2216;
23
+ --accent: #5a3fc0;
24
+ --accent-fill: #5a3fc0;
9
25
  --accent-text: #ffffff;
10
- --danger: #c93c37;
11
- --ok: #1f8a4c;
12
- --warn: #b7791f;
13
- --shadow: 0 1px 2px rgba(16, 24, 40, 0.06), 0 1px 3px rgba(16, 24, 40, 0.08);
26
+ --danger: #a8302b;
27
+ --ok: #1d6e40;
28
+ --warn: #8a5300;
29
+ --gold: #b8892f;
30
+ --gold-ink: #7a5715;
31
+ --focus: #5a3fc0;
32
+ --wordmark: linear-gradient(180deg, #a77a26 0%, #7a5715 55%, #563c0b 100%);
33
+ --shadow: 0 1px 2px rgba(70, 48, 12, 0.08), 0 4px 14px rgba(70, 48, 12, 0.08);
14
34
  --term-bg: #0f1115;
15
- --radius: 10px;
35
+ --radius: 6px;
36
+ --ease: cubic-bezier(0.2, 0.8, 0.2, 1);
37
+ --font-display: "Cinzel", "Cinzel Fallback", "Palatino Linotype", Palatino, Georgia, serif;
38
+ --font-mono: ui-monospace, "Cascadia Code", "SF Mono", Menlo, Consolas, monospace;
39
+ --icon-sun: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='4.2'/%3E%3Cpath d='M12 2.5v2.2M12 19.3v2.2M2.5 12h2.2M19.3 12h2.2M5.3 5.3l1.6 1.6M17.1 17.1l1.6 1.6M5.3 18.7l1.6-1.6M17.1 6.9l1.6-1.6'/%3E%3C/svg%3E");
40
+ --icon-moon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'%3E%3Cpath d='M19.5 14.6A8 8 0 0 1 9.4 4.5a8 8 0 1 0 10.1 10.1z'/%3E%3C/svg%3E");
41
+ --icon-external: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 17L17 7M9 7h8v8'/%3E%3C/svg%3E");
42
+ --icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 5.5l6.5 6.5L9 18.5'/%3E%3C/svg%3E");
43
+ --icon-info: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 10.8v6.2' stroke-width='2.4'/%3E%3Ccircle cx='12' cy='7.3' r='1.2' fill='black' stroke='none'/%3E%3C/svg%3E");
16
44
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
17
45
  font-size: 15px;
18
46
  color-scheme: light;
47
+ scrollbar-color: color-mix(in srgb, var(--muted) 45%, transparent) transparent;
19
48
  }
20
49
 
21
50
  /* theme.js sets data-theme from the saved choice or the system setting before the first paint. */
@@ -26,20 +55,31 @@
26
55
  --border: #2a303b;
27
56
  --text: #e6e9ef;
28
57
  --muted: #9aa4b2;
29
- --accent: #7c7cf0;
58
+ --heading: #f1e2c2;
59
+ --accent: #ac9ff7;
60
+ --accent-fill: #5b40d0;
30
61
  --danger: #ef6b66;
31
62
  --ok: #4cc38a;
32
63
  --warn: #e0a84a;
64
+ --gold: #e8c47c;
65
+ --gold-ink: #e8c47c;
66
+ --focus: #e8c47c;
67
+ --wordmark: linear-gradient(180deg, #fbe9bd 0%, #e2b867 55%, #a97b35 100%);
33
68
  --shadow: none;
34
69
  color-scheme: dark;
35
70
  }
36
71
 
37
72
  * { box-sizing: border-box; }
38
73
  body { margin: 0; background: var(--bg); color: var(--text); min-height: 100vh; }
39
- h1, h2 { margin: 0; }
40
- h1 { font-size: 1.1rem; font-weight: 650; }
41
- h2 { font-size: 1rem; font-weight: 600; }
42
- code, pre { font-family: ui-monospace, "Cascadia Code", Menlo, Consolas, monospace; }
74
+ ::selection { background: color-mix(in srgb, var(--accent) 32%, transparent); }
75
+ h1, h2 { margin: 0; font-family: var(--font-display); color: var(--heading); }
76
+ h1 {
77
+ font-size: 1.32rem; font-weight: 700; letter-spacing: 0.02em; white-space: nowrap;
78
+ background: var(--wordmark); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
79
+ }
80
+ h2 { font-size: 1.02rem; font-weight: 600; letter-spacing: 0.03em; }
81
+ h2 .count { font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; letter-spacing: 0; }
82
+ code, pre { font-family: var(--font-mono); }
43
83
  [hidden] { display: none !important; }
44
84
 
45
85
  .topbar {
@@ -48,31 +88,41 @@ code, pre { font-family: ui-monospace, "Cascadia Code", Menlo, Consolas, monospa
48
88
  position: sticky; top: 0; z-index: 5;
49
89
  }
50
90
  .brand { display: flex; align-items: center; gap: 10px; }
51
- .brand-mark { width: 26px; height: 26px; color: var(--accent); flex: none; }
91
+ .version {
92
+ position: relative; font-family: inherit; font-size: 0.72rem; font-weight: 600; padding: 1px 7px; border-radius: 999px; white-space: nowrap;
93
+ background: var(--surface-2); color: var(--muted); border: 1px solid var(--border); font-variant-numeric: tabular-nums; cursor: pointer;
94
+ }
95
+ .version:hover { color: var(--text); border-color: var(--muted); }
96
+ .version:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
97
+ .version.unread::after {
98
+ content: ""; position: absolute; top: -3px; right: -3px; width: 8px; height: 8px; border-radius: 50%;
99
+ background: var(--accent); box-shadow: 0 0 0 2px var(--surface);
100
+ }
52
101
  .topbar-end { display: flex; align-items: center; justify-content: flex-end; gap: 14px; flex-wrap: wrap; min-width: 0; }
53
102
  .connection { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 0.85rem; }
54
- .connection .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--warn); }
55
- .connection.ok .dot { background: var(--ok); }
56
- .connection.down .dot { background: var(--danger); }
103
+ .connection .dot { --dot: var(--warn); width: 8px; height: 8px; border-radius: 50%; background: var(--dot); }
104
+ .connection.ok .dot { --dot: var(--ok); }
105
+ .connection.down .dot { --dot: var(--danger); }
57
106
 
58
- main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; display: grid; gap: 28px; }
107
+ main { max-width: 1200px; margin: 0 auto; padding: 26px 16px 56px; display: grid; grid-template-columns: minmax(0, 1fr); gap: 34px; }
59
108
  .section-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
60
109
  .count { color: var(--muted); font-weight: 500; }
61
110
 
62
111
  .cwd { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 0.85rem; flex: 1 1 280px; max-width: 520px; }
63
112
  .cwd input, .auth input {
64
- flex: 1; min-width: 0; padding: 7px 10px; border-radius: 8px; border: 1px solid var(--border);
113
+ flex: 1; min-width: 0; padding: 7px 10px; border-radius: var(--radius); border: 1px solid var(--border);
65
114
  background: var(--surface); color: var(--text); font: inherit; font-size: 0.9rem;
66
115
  }
67
- .cwd input:focus, .auth input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
116
+ .cwd input:focus, .auth input:focus { outline: 2px solid var(--focus); outline-offset: 1px; }
68
117
 
69
118
  .providers { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; }
70
119
  .provider {
71
- display: grid; grid-template-columns: auto 1fr; align-items: center; align-content: start; gap: 10px 12px; padding: 14px;
120
+ display: flex; flex-direction: column; gap: 10px; padding: 14px;
72
121
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); box-shadow: var(--shadow);
73
122
  }
123
+ .provider-head { display: flex; align-items: center; gap: 12px; min-width: 0; }
74
124
  .provider.unavailable .provider-icon { filter: grayscale(1); opacity: 0.45; }
75
- .provider-text { display: grid; gap: 2px; min-width: 0; }
125
+ .provider-text { flex: 1; display: grid; gap: 2px; min-width: 0; }
76
126
  .provider .vendor-line { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 6px; min-width: 0; }
77
127
  .provider .vendor { font-weight: 600; }
78
128
  .provider .tier {
@@ -85,17 +135,17 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; display: grid
85
135
  .provider .state.update-available { color: var(--warn); }
86
136
  .provider.unavailable .state { color: var(--muted); }
87
137
  .provider .update { color: var(--warn); border-color: var(--warn); }
88
- .provider .accounts { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 6px; }
138
+ .provider .accounts { display: flex; flex-wrap: wrap; gap: 6px; }
89
139
  .account-chip {
90
140
  font: inherit; font-size: 0.75rem; font-weight: 600; padding: 2px 10px; border-radius: 999px; cursor: pointer;
91
141
  border: 1px solid var(--border); background: var(--surface-2); color: var(--muted); max-width: 100%;
92
142
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
93
143
  }
94
144
  .account-chip:hover { border-color: var(--muted); }
95
- .account-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
96
- .account-chip[aria-selected="true"] { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
145
+ .account-chip:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
146
+ .account-chip[aria-selected="true"] { background: var(--accent-fill); border-color: var(--accent-fill); color: var(--accent-text); }
97
147
  .account-chip.unsigned { border-style: dashed; }
98
- .provider .usage { grid-column: 1 / -1; display: grid; gap: 4px; }
148
+ .provider .usage { display: grid; gap: 4px; }
99
149
  .provider .usage:empty { display: none; }
100
150
  .meter { display: grid; grid-template-columns: 5.5em 1fr auto; align-items: center; gap: 8px; font-size: 0.75rem; color: var(--muted); }
101
151
  .meter-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@@ -106,7 +156,7 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; display: grid
106
156
  .meter-value { white-space: nowrap; font-variant-numeric: tabular-nums; }
107
157
  .usage-note { font-size: 0.75rem; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
108
158
  .provider .model-stats {
109
- grid-column: 1 / -1; display: grid; grid-template-columns: max-content minmax(24px, 1fr) auto; align-items: center; gap: 2px 8px;
159
+ display: grid; grid-template-columns: max-content minmax(24px, 1fr) auto; align-items: center; gap: 2px 8px;
110
160
  }
111
161
  .provider .model-stats:empty { display: none; }
112
162
  .provider .model-stats > .usage-note { grid-column: 1 / -1; contain: inline-size; }
@@ -115,9 +165,13 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; display: grid
115
165
  font: inherit; font-size: 0.78rem; text-align: left; cursor: pointer;
116
166
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
117
167
  }
118
- .model-stats-head::after { content: " ›"; }
168
+ .model-stats-head::after, .console-link::after, .theme-toggle::before, .model-name::before, .provider .copies summary::before {
169
+ content: ""; display: inline-block; flex: none; width: 0.75em; height: 0.75em; margin-left: 0.3em; vertical-align: -0.05em;
170
+ background: currentColor; mask: var(--icon-chevron) center / contain no-repeat;
171
+ }
172
+ .console-link::after { width: 0.7em; height: 0.7em; margin-left: 0.25em; mask-image: var(--icon-external); }
119
173
  .model-stats-head:hover { text-decoration: underline; }
120
- .model-stats-head:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
174
+ .model-stats-head:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 3px; }
121
175
 
122
176
  .stat {
123
177
  --tier: var(--border);
@@ -127,16 +181,16 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; display: grid
127
181
  .stat-label { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
128
182
  .stat-reading { grid-column: 2 / -1; display: grid; grid-template-columns: subgrid; align-items: center; }
129
183
  .info {
130
- position: relative; flex: none; display: inline-grid; place-items: center; width: 1.3em; height: 1.3em; padding: 0;
131
- border: 1px solid color-mix(in srgb, currentColor 50%, transparent); border-radius: 50%; background: none; color: var(--muted);
132
- font: italic 700 0.68rem/1 Georgia, "Times New Roman", serif; cursor: help;
184
+ position: relative; flex: none; display: inline-grid; place-items: center; width: 0.9rem; height: 0.9rem; padding: 0;
185
+ border: 0; border-radius: 50%; background: none; color: var(--muted); font-size: 0; cursor: help;
133
186
  }
187
+ .info::before { content: ""; position: absolute; inset: 0; background: currentColor; mask: var(--icon-info) center / contain no-repeat; }
134
188
  .info::after { content: ""; position: absolute; inset: -6px; }
135
- .info:hover, .info:focus-visible { color: var(--accent); border-color: currentColor; }
136
- .info:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
189
+ .info:hover, .info:focus-visible { color: var(--accent); }
190
+ .info:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
137
191
  .tip {
138
192
  position: fixed; z-index: 30; width: max-content; max-width: min(320px, calc(100vw - 16px)); margin: 0; padding: 9px 11px;
139
- border-radius: 8px; background: var(--text); color: var(--bg); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
193
+ border-radius: var(--radius); background: var(--text); color: var(--bg); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
140
194
  font-size: 0.78rem; line-height: 1.45; pointer-events: none;
141
195
  }
142
196
  .tip strong { font-weight: 600; }
@@ -168,14 +222,17 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; display: grid
168
222
  .tier-c { --tier: #4ade80; --tier-ink: #c6f6d5; }
169
223
  .tier-d { --tier: #94a3b8; --tier-ink: #d4dbe4; }
170
224
  }
171
- .provider-links { grid-column: 1 / -1; display: flex; gap: 14px; font-size: 0.78rem; }
225
+ .provider-links { display: flex; gap: 14px; font-size: 0.78rem; }
172
226
  .console-link { color: var(--accent); text-decoration: none; }
173
227
  .console-link:hover { text-decoration: underline; }
174
- .console-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
175
- .provider-actions { grid-column: 1 / -1; display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
228
+ .console-link:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 3px; }
229
+ .provider-actions { margin-top: auto; display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
176
230
  .provider .hint { font-size: 0.78rem; color: var(--muted); overflow-wrap: anywhere; }
177
- .provider .copies { grid-column: 1 / -1; font-size: 0.78rem; color: var(--muted); overflow-wrap: anywhere; }
178
- .provider .copies summary { cursor: pointer; color: var(--warn); }
231
+ .provider .copies { font-size: 0.78rem; color: var(--muted); overflow-wrap: anywhere; }
232
+ .provider .copies summary { cursor: pointer; color: var(--warn); list-style: none; }
233
+ .provider .copies summary::-webkit-details-marker { display: none; }
234
+ .provider .copies summary::before { margin: 0 0.3em 0 0; transition: transform 0.15s var(--ease); }
235
+ .provider .copies[open] summary::before { transform: rotate(90deg); }
179
236
  .provider .copies ul { margin: 6px 0 0; padding: 0; list-style: none; display: grid; gap: 8px; }
180
237
  .provider .copies li span { display: block; }
181
238
  .provider .copies .copy-name { color: var(--text); }
@@ -196,8 +253,8 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; display: grid
196
253
  display: grid; gap: 12px; padding: 14px; border: 1px solid var(--border); border-radius: var(--radius);
197
254
  background: var(--surface); box-shadow: var(--shadow); cursor: pointer;
198
255
  }
199
- .session-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
200
- .session-card.exited { opacity: 0.75; }
256
+ .session-card:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
257
+ .session-card.exited .name { color: var(--muted); }
201
258
  .card-top { display: flex; align-items: center; gap: 12px; }
202
259
  .card-title { flex: 1; min-width: 0; }
203
260
  .card-title .name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@@ -214,10 +271,13 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; display: grid
214
271
  border: 0; font-family: inherit; cursor: pointer;
215
272
  }
216
273
  .model-pill:hover { background: color-mix(in srgb, var(--accent) 24%, var(--surface)); }
217
- .model-pill:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
274
+ .model-pill:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
218
275
  .model-pill.screen { font-weight: 500; }
219
276
  .status-pill.active { color: var(--ok); }
220
- .status-pill.active::before { content: "● "; animation: pulse 1.2s ease-in-out infinite; }
277
+ .status-pill.active::before {
278
+ content: ""; display: inline-block; width: 6px; height: 6px; margin-right: 5px; vertical-align: 1px; border-radius: 50%;
279
+ background: currentColor; box-shadow: 0 0 6px currentColor; animation: pulse 1.2s ease-in-out infinite;
280
+ }
221
281
  .status-pill.exited { color: var(--danger); }
222
282
 
223
283
  .agents-row { display: flex; align-items: center; gap: 10px; min-height: 30px; }
@@ -240,27 +300,35 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; display: grid
240
300
 
241
301
  .card-actions { display: flex; gap: 8px; flex-wrap: wrap; }
242
302
  .btn {
243
- padding: 6px 12px; border-radius: 8px; border: 1px solid var(--border); background: var(--surface-2);
303
+ padding: 6px 12px; border-radius: var(--radius); border: 1px solid var(--border); background: var(--surface-2);
244
304
  color: var(--text); font: inherit; font-size: 0.85rem; cursor: pointer;
305
+ transition: border-color 0.15s, box-shadow 0.15s, filter 0.15s, transform 0.1s;
245
306
  }
307
+ .btn:active:not(:disabled) { transform: translateY(1px); }
246
308
  .btn:hover { border-color: var(--muted); }
247
- .btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
248
- .btn.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
309
+ .btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
310
+ .btn.primary { background: var(--accent-fill); border-color: var(--accent-fill); color: var(--accent-text); }
249
311
  .btn.danger { color: var(--danger); }
250
312
  .btn.danger:hover { border-color: var(--danger); }
251
313
  .btn:disabled { opacity: 0.6; cursor: progress; }
252
- .stop-manager, .theme-toggle, .upgrade { white-space: nowrap; }
253
- .btn.upgrade { color: var(--warn); border-color: var(--warn); }
314
+ .stop-manager, .restart-manager, .theme-toggle, .upgrade { white-space: nowrap; }
315
+ .theme-toggle::before { width: 1em; height: 1em; margin: 0 0.4em 0 0; vertical-align: -0.15em; mask-image: var(--icon-sun); }
316
+ .theme-toggle[data-next="dark"]::before { mask-image: var(--icon-moon); }
317
+ .btn.upgrade, .btn.restart-manager.pending { color: var(--warn); border-color: var(--warn); }
254
318
  .upgrade-note { font-size: 0.85rem; color: var(--warn); }
255
319
 
256
320
  .empty { color: var(--muted); margin: 8px 0 0; }
257
321
 
258
322
  .auth { max-width: 560px; margin: 60px auto; padding: 24px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); display: grid; gap: 12px; }
259
323
  .auth p { margin: 0; color: var(--muted); line-height: 1.5; }
260
- .auth pre { margin: 0; padding: 10px 12px; background: var(--surface-2); border-radius: 8px; }
324
+ .auth pre { margin: 0; padding: 10px 12px; background: var(--surface-2); border-radius: var(--radius); }
261
325
  .auth form { display: flex; gap: 8px; }
326
+ .stopped-help { display: grid; gap: 12px; }
327
+ .command { display: flex; align-items: center; gap: 8px; }
328
+ .command pre { flex: 1; min-width: 0; overflow-x: auto; }
329
+ .stopped-help code { color: var(--text); overflow-wrap: anywhere; }
262
330
  .notice h2 { color: var(--danger); }
263
- .notice.stopping h2 { color: var(--warn); }
331
+ .notice.stopping h2, .notice.restarting h2 { color: var(--warn); }
264
332
  .error { color: var(--danger); min-height: 1.2em; }
265
333
 
266
334
  .terminal-panel {
@@ -305,10 +373,10 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; display: grid
305
373
  font: inherit; font-size: 0.85rem; text-align: left; cursor: pointer;
306
374
  }
307
375
  .model-toggle:hover { background: var(--surface-2); }
308
- .model-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
376
+ .model-toggle:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
309
377
  .model-title { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; min-width: 0; }
310
378
  .model-name { font-weight: 600; overflow-wrap: anywhere; }
311
- .model-name::before { content: "▸"; content: "▸" / ""; display: inline-block; width: 1em; color: var(--muted); transition: transform 0.15s; }
379
+ .model-name::before { width: 0.7em; height: 0.7em; margin: 0 0.3em 0 0; background-color: var(--muted); transition: transform 0.15s var(--ease); }
312
380
  .model-toggle[aria-expanded="true"] .model-name::before { transform: rotate(90deg); }
313
381
  .model-context { color: var(--muted); font-variant-numeric: tabular-nums; }
314
382
  .badge {
@@ -317,10 +385,10 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; display: grid
317
385
  }
318
386
  .badge.in-use { --badge: var(--accent); color: color-mix(in srgb, var(--badge) 80%, #000); }
319
387
  .badge.new { --badge: var(--ok); color: color-mix(in srgb, var(--badge) 72%, #000); }
320
- .badge.expires { --badge: var(--warn); color: color-mix(in srgb, var(--badge) 62%, #000); }
321
- .badge.in-use, .badge.new, .badge.expires { border-color: color-mix(in srgb, var(--badge) 45%, transparent); }
388
+ .badge.expires, .badge.installed { --badge: var(--warn); color: color-mix(in srgb, var(--badge) 62%, #000); }
389
+ .badge.in-use, .badge.new, .badge.expires, .badge.installed { border-color: color-mix(in srgb, var(--badge) 45%, transparent); }
322
390
  :where(:root[data-theme="dark"]) {
323
- .badge.in-use, .badge.new, .badge.expires { color: var(--badge); }
391
+ .badge.in-use, .badge.new, .badge.expires, .badge.installed { color: var(--badge); }
324
392
  }
325
393
  .model-detail {
326
394
  display: grid; grid-template-columns: max-content minmax(48px, 1fr) auto minmax(0, 19em); gap: 14px 10px;
@@ -352,7 +420,7 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; display: grid
352
420
  .news-link { color: var(--text); font-weight: 600; text-decoration: none; }
353
421
  a.news-link:hover, .news-discussion:hover { text-decoration: underline; }
354
422
  a.news-link:visited { color: var(--muted); }
355
- .news-link:focus-visible, .news-discussion:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
423
+ .news-link:focus-visible, .news-discussion:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 3px; }
356
424
  .news-meta { color: var(--muted); font-size: 0.78rem; white-space: nowrap; font-variant-numeric: tabular-nums; }
357
425
 
358
426
  .news-panel {
@@ -360,7 +428,19 @@ a.news-link:visited { color: var(--muted); }
360
428
  border: 0; border-left: 1px solid var(--border); background: var(--surface); color: var(--text);
361
429
  box-shadow: -16px 0 48px rgba(0, 0, 0, 0.25);
362
430
  }
363
- .news-panel[open] { display: flex; flex-direction: column; animation: news-in 0.18s ease-out; }
431
+ .news-panel[open] { display: flex; flex-direction: column; }
432
+ .models, .news-panel {
433
+ transition: opacity 0.22s var(--ease), transform 0.22s var(--ease), overlay 0.22s allow-discrete, display 0.22s allow-discrete;
434
+ }
435
+ .models:not([open]) { opacity: 0; transform: translateY(12px) scale(0.98); }
436
+ .news-panel:not([open]) { opacity: 0; transform: translateX(28px); }
437
+ .models::backdrop, .news-panel::backdrop { transition: opacity 0.22s, overlay 0.22s allow-discrete, display 0.22s allow-discrete; }
438
+ .models:not([open])::backdrop, .news-panel:not([open])::backdrop { opacity: 0; }
439
+ @starting-style {
440
+ .models[open] { opacity: 0; transform: translateY(12px) scale(0.98); }
441
+ .news-panel[open] { opacity: 0; transform: translateX(28px); }
442
+ .models[open]::backdrop, .news-panel[open]::backdrop { opacity: 0; }
443
+ }
364
444
  .news-panel::backdrop { background: rgba(15, 17, 21, 0.4); }
365
445
  .news-bar { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--border); }
366
446
  .news-heading { flex: 1; min-width: 0; }
@@ -371,8 +451,8 @@ a.news-link:visited { color: var(--muted); }
371
451
  border: 1px solid var(--border); background: var(--surface-2); color: var(--muted);
372
452
  }
373
453
  .news-filter:hover { border-color: var(--muted); }
374
- .news-filter:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
375
- .news-filter[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
454
+ .news-filter:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
455
+ .news-filter[aria-pressed="true"] { background: var(--accent-fill); border-color: var(--accent-fill); color: var(--accent-text); }
376
456
  .news-body { flex: 1; min-height: 0; overflow: auto; padding: 0 14px 14px; }
377
457
  .news-fresh { width: 100%; margin-top: 12px; }
378
458
  .news-day {
@@ -394,20 +474,77 @@ a.news-link:visited { color: var(--muted); }
394
474
  .news-status { margin: 0; padding: 10px 14px; border-top: 1px solid var(--border); color: var(--muted); font-size: 0.75rem; line-height: 1.45; }
395
475
  .news-status span { display: block; }
396
476
 
477
+ .changelog-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
478
+ .changelog-actions .btn { flex: 1 1 auto; }
479
+ .changelog-list { list-style: none; margin: 0; padding: 0; }
480
+ .changelog-release { padding: 14px 0 12px; }
481
+ .changelog-release + .changelog-release { border-top: 1px solid var(--border); }
482
+ .changelog-release h3 { margin: 0; font-size: 1rem; }
483
+ .changelog-release .news-meta { display: block; margin-top: 2px; }
484
+ .changelog-type { margin: 10px 0 4px; font-size: 0.7rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); }
485
+ .changelog-type.breaking { color: var(--danger); }
486
+ .changelog-changes { margin: 0; padding-left: 1.2em; display: grid; gap: 4px; list-style: disc; font-size: 0.85rem; line-height: 1.45; overflow-wrap: anywhere; }
487
+ .changelog-changes li::marker { color: var(--muted); }
488
+ .changelog-changes code { font-size: 0.8rem; padding: 0 4px; border-radius: 4px; background: var(--surface-2); }
489
+
490
+ .history-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 10px 14px 0; }
491
+ .history-tools input[type="search"] {
492
+ flex: 1 1 220px; min-width: 0; padding: 7px 10px; border-radius: var(--radius); border: 1px solid var(--border);
493
+ background: var(--surface); color: var(--text); font: inherit; font-size: 0.9rem;
494
+ }
495
+ .history-tools input:focus-visible, .history-form input:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
496
+ .history-here { display: flex; align-items: center; gap: 6px; font-size: 0.8rem; color: var(--muted); white-space: nowrap; cursor: pointer; }
497
+ .history-here:has(input:disabled) { opacity: 0.6; cursor: default; }
498
+ .history .models-body { padding-top: 6px; }
499
+ .history-row {
500
+ display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: 4px 12px;
501
+ padding: 10px 8px; border-bottom: 1px solid var(--border);
502
+ }
503
+ .history-main { min-width: 0; }
504
+ .history-title { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
505
+ .history-row.untitled .history-title { font-weight: 500; color: var(--muted); }
506
+ .history-meta { color: var(--muted); font-size: 0.78rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
507
+ .history-row.running .history-meta { color: var(--ok); }
508
+ .session-id {
509
+ font-family: ui-monospace, "Cascadia Code", "SF Mono", Menlo, Consolas, monospace; font-size: 0.72rem; padding: 2px 7px;
510
+ border-radius: 6px; border: 1px solid var(--border); background: var(--surface-2); color: var(--muted); cursor: copy; white-space: nowrap;
511
+ }
512
+ .session-id:hover { color: var(--text); border-color: var(--muted); }
513
+ .session-id:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
514
+ .card-title .meta { display: flex; align-items: center; gap: 8px; min-width: 0; }
515
+ .card-title .meta-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
516
+ .history-form { display: flex; align-items: center; gap: 8px; padding: 10px 14px; border-top: 1px solid var(--border); font-size: 0.85rem; color: var(--muted); }
517
+ .history-form input {
518
+ flex: 1; min-width: 0; padding: 6px 10px; border-radius: var(--radius); border: 1px solid var(--border);
519
+ background: var(--surface); color: var(--text); font: inherit; font-size: 0.85rem;
520
+ }
521
+
397
522
  .toast {
398
523
  position: fixed; left: 50%; bottom: 20px; transform: translateX(-50%); z-index: 20;
399
- max-width: min(640px, calc(100vw - 32px)); padding: 10px 14px; border-radius: 8px;
524
+ max-width: min(640px, calc(100vw - 32px)); padding: 10px 14px; border-radius: var(--radius);
400
525
  background: var(--text); color: var(--bg); font-size: 0.9rem; box-shadow: var(--shadow); white-space: pre-wrap;
401
526
  }
402
527
 
528
+ .toast:not([hidden]) { animation: toast-in 0.25s var(--ease); }
529
+ .tip:not([hidden]) { animation: fade-in 0.12s ease-out; }
530
+
531
+ ::view-transition-old(root), ::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
532
+ ::view-transition-new(root) { animation: theme-reveal 0.6s var(--ease); }
533
+
403
534
  @keyframes pulse { 50% { opacity: 0.35; } }
404
535
  @keyframes ring { 0% { transform: scale(0.85); opacity: 0.8; } 100% { transform: scale(1.3); opacity: 0; } }
405
536
  @keyframes stat-fill { from { transform: scaleX(0); } }
406
- @keyframes news-in { from { transform: translateX(24px); opacity: 0; } }
537
+ @keyframes toast-in { from { opacity: 0; transform: translate(-50%, 10px); } }
538
+ @keyframes fade-in { from { opacity: 0; } }
539
+ @keyframes theme-reveal {
540
+ from { clip-path: circle(0 at var(--reveal-x) var(--reveal-y)); }
541
+ to { clip-path: circle(var(--reveal-r) at var(--reveal-x) var(--reveal-y)); }
542
+ }
407
543
 
408
544
  @media (prefers-reduced-motion: reduce) {
409
- .status-pill.active::before, .agent.working::after, .model-detail .stat-fill, .news-panel[open] { animation: none; }
410
- .model-name::before { transition: none; }
545
+ .status-pill.active::before, .agent.working::after, .model-detail .stat-fill, .toast:not([hidden]), .tip:not([hidden]) { animation: none; }
546
+ .model-name::before, .provider .copies summary::before, .btn, .models, .news-panel, .models::backdrop, .news-panel::backdrop { transition: none; }
547
+ .btn:active:not(:disabled) { transform: none; }
411
548
  }
412
549
 
413
550
  @media (max-width: 640px) {
@@ -427,4 +564,7 @@ a.news-link:visited { color: var(--muted); }
427
564
  .news-row { flex-wrap: wrap; }
428
565
  .news-row .news-link { flex-basis: 100%; white-space: normal; }
429
566
  .news-panel { border-left: 0; }
567
+ .history-row { grid-template-columns: minmax(0, 1fr) auto; }
568
+ .history-row .session-id { grid-row: 2; justify-self: start; }
569
+ .history-form { flex-wrap: wrap; }
430
570
  }
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/web/art/page.png DELETED
Binary file