@oddessentials/agent-guild 0.1.1 → 0.3.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.
- package/README.md +20 -7
- package/config/providers.default.json +10 -0
- package/package.json +1 -1
- package/src/manager/config.mjs +7 -1
- package/src/manager/main.mjs +20 -7
- package/src/manager/model-stats.mjs +338 -0
- package/src/manager/providers.mjs +89 -5
- package/src/manager/self-update.mjs +205 -0
- package/src/manager/server.mjs +14 -1
- package/src/manager/session-manager.mjs +58 -7
- package/src/manager/session.mjs +4 -1
- package/src/manager/usage.mjs +106 -25
- package/web/app.js +663 -13
- package/web/art/art.css +52 -6
- package/web/index.html +49 -1
- package/web/styles.css +165 -18
- package/web/theme.js +10 -0
package/web/art/art.css
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
.level-badge { display: none; }
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
/* The guild look is the dark theme. The rules below nest under the theme
|
|
4
|
+
attribute that theme.js sets on <html>, so they apply whether the user
|
|
5
|
+
chose dark or the system did. :where() keeps their specificity as it was
|
|
6
|
+
inside the media query, so styles.css still loses to them only on order. */
|
|
7
|
+
:where(:root[data-theme="dark"]) {
|
|
8
|
+
--gold: #e8c47c;
|
|
9
|
+
--gold-dim: #8a6d3b;
|
|
10
|
+
--card-bg: rgba(18, 20, 26, 0.9);
|
|
9
11
|
|
|
10
12
|
.provider, .session-card {
|
|
11
13
|
--pc: #a67cf6;
|
|
@@ -109,6 +111,50 @@
|
|
|
109
111
|
.meter.low .meter-fill { background: var(--warn); box-shadow: 0 0 8px rgba(224, 168, 74, 0.5); }
|
|
110
112
|
.meter.empty .meter-fill { background: var(--danger); box-shadow: 0 0 8px rgba(239, 107, 102, 0.5); }
|
|
111
113
|
|
|
114
|
+
.model-stats-head { color: var(--gold); }
|
|
115
|
+
.info { color: #b89a5e; }
|
|
116
|
+
.info:hover, .info:focus-visible { color: var(--gold); }
|
|
117
|
+
.tip {
|
|
118
|
+
background: #12141a; color: #e9e2cf; border: 1px solid #4a3d25;
|
|
119
|
+
box-shadow: inset 0 0 0 1px rgba(232, 196, 124, 0.06), 0 10px 28px rgba(0, 0, 0, 0.6);
|
|
120
|
+
}
|
|
121
|
+
.tip strong { color: var(--gold); font-family: "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif; }
|
|
122
|
+
.stat-bar { height: 7px; background: #0c0e12; box-shadow: inset 0 0 0 1px rgba(232, 196, 124, 0.18); }
|
|
123
|
+
.stat-fill {
|
|
124
|
+
background: linear-gradient(90deg, color-mix(in srgb, var(--tier) 55%, #000), var(--tier));
|
|
125
|
+
box-shadow: 0 0 8px color-mix(in srgb, var(--tier) 50%, transparent);
|
|
126
|
+
}
|
|
127
|
+
.stat-tier {
|
|
128
|
+
border-radius: 3px; font-family: "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif;
|
|
129
|
+
background: linear-gradient(color-mix(in srgb, var(--tier) 34%, #1a1d26), #0d0f15);
|
|
130
|
+
border-color: color-mix(in srgb, var(--tier) 70%, #000);
|
|
131
|
+
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), 0 0 6px color-mix(in srgb, var(--tier) 30%, transparent);
|
|
132
|
+
}
|
|
133
|
+
.tier-s .stat-tier {
|
|
134
|
+
color: #2b1b06; border-color: #f6dea6;
|
|
135
|
+
background: linear-gradient(180deg, #fbe9bd 0%, #e2b867 55%, #a97b35 100%);
|
|
136
|
+
box-shadow: 0 0 10px rgba(232, 196, 124, 0.6);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.models {
|
|
140
|
+
border-radius: 6px; border-color: #4a3d25; background: #12141a;
|
|
141
|
+
box-shadow: inset 0 0 0 1px rgba(232, 196, 124, 0.06), 0 24px 60px rgba(0, 0, 0, 0.6);
|
|
142
|
+
}
|
|
143
|
+
.models::after {
|
|
144
|
+
content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
|
|
145
|
+
border: 44px solid transparent; border-image: url("/art/ui/frame.png") 168;
|
|
146
|
+
}
|
|
147
|
+
.models::backdrop { background: rgba(5, 6, 9, 0.72); }
|
|
148
|
+
.models-bar { padding: 20px 24px 12px; }
|
|
149
|
+
.models-body { padding: 0 24px 14px; }
|
|
150
|
+
.models-source { padding: 10px 24px 20px; }
|
|
151
|
+
.models-bar, .models-source, .model-columns, .model { border-color: #2a2418; }
|
|
152
|
+
.model-columns { background: #12141a; }
|
|
153
|
+
.model-toggle:hover { background: rgba(232, 196, 124, 0.06); }
|
|
154
|
+
.model-group h4 { color: #c9ab72; }
|
|
155
|
+
.badge { background: rgba(0, 0, 0, 0.45); border-color: #4a3d25; }
|
|
156
|
+
.model-pill:hover { border-color: var(--gold-dim); }
|
|
157
|
+
|
|
112
158
|
.session-card { padding-left: 152px; min-height: 196px; }
|
|
113
159
|
.session-card::before {
|
|
114
160
|
inset: 0 auto 0 0; width: 168px; background-size: 168px auto;
|
package/web/index.html
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<title>Agent Guild</title>
|
|
7
7
|
<meta name="color-scheme" content="light dark">
|
|
8
|
+
<script src="/theme.js"></script>
|
|
8
9
|
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='8' fill='%235B5BD6'/%3E%3Cpath d='M9 22l7-12 7 12' stroke='white' stroke-width='3' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E">
|
|
9
10
|
<link rel="stylesheet" href="/vendor/xterm/xterm.css">
|
|
10
11
|
<link rel="stylesheet" href="/styles.css">
|
|
@@ -20,6 +21,9 @@
|
|
|
20
21
|
<div id="connection" class="connection" role="status" aria-live="polite">
|
|
21
22
|
<span class="dot"></span><span class="label">Connecting…</span>
|
|
22
23
|
</div>
|
|
24
|
+
<span id="upgrade-note" class="upgrade-note" hidden></span>
|
|
25
|
+
<button id="upgrade" class="btn upgrade" type="button" hidden></button>
|
|
26
|
+
<button id="theme-toggle" class="btn theme-toggle" type="button"></button>
|
|
23
27
|
<button id="stop-manager" class="btn danger stop-manager" type="button" hidden title="Stop the session manager. This ends every session.">Stop manager</button>
|
|
24
28
|
</div>
|
|
25
29
|
</header>
|
|
@@ -83,6 +87,26 @@
|
|
|
83
87
|
<div id="terminal-host" class="terminal-host"></div>
|
|
84
88
|
</div>
|
|
85
89
|
|
|
90
|
+
<dialog id="models" class="models" aria-labelledby="models-title">
|
|
91
|
+
<div class="models-bar">
|
|
92
|
+
<span id="models-icon" class="provider-icon small"></span>
|
|
93
|
+
<div class="models-heading">
|
|
94
|
+
<h2 id="models-title"></h2>
|
|
95
|
+
<p id="models-sub" class="sub"></p>
|
|
96
|
+
</div>
|
|
97
|
+
<button id="models-close" class="btn" type="button">Close</button>
|
|
98
|
+
</div>
|
|
99
|
+
<div class="models-body">
|
|
100
|
+
<div id="models-columns" class="model-columns" aria-hidden="true"></div>
|
|
101
|
+
<div id="models-list"></div>
|
|
102
|
+
<button id="models-more" class="btn models-more" type="button" hidden></button>
|
|
103
|
+
<p id="models-note" class="models-note"></p>
|
|
104
|
+
</div>
|
|
105
|
+
<p id="models-source" class="models-source"></p>
|
|
106
|
+
</dialog>
|
|
107
|
+
|
|
108
|
+
<div id="tip" class="tip" aria-hidden="true" hidden><strong id="tip-title"></strong><span id="tip-source"></span><p id="tip-text"></p></div>
|
|
109
|
+
|
|
86
110
|
<div id="toast" class="toast" role="alert" hidden></div>
|
|
87
111
|
|
|
88
112
|
<template id="provider-template">
|
|
@@ -93,7 +117,9 @@
|
|
|
93
117
|
<span class="tool"></span>
|
|
94
118
|
<span class="state"></span>
|
|
95
119
|
</span>
|
|
120
|
+
<div class="accounts" role="tablist" aria-label="Accounts" hidden></div>
|
|
96
121
|
<div class="usage"></div>
|
|
122
|
+
<div class="model-stats"></div>
|
|
97
123
|
<div class="provider-links">
|
|
98
124
|
<a class="console-link usage-link" target="_blank" rel="noopener noreferrer">Usage ↗</a>
|
|
99
125
|
<a class="console-link billing-link" target="_blank" rel="noopener noreferrer">Billing ↗</a>
|
|
@@ -120,6 +146,28 @@
|
|
|
120
146
|
</div>
|
|
121
147
|
</template>
|
|
122
148
|
|
|
149
|
+
<template id="stat-template">
|
|
150
|
+
<div class="stat">
|
|
151
|
+
<span class="stat-label"><span class="stat-name"></span><button class="info" type="button">i</button></span>
|
|
152
|
+
<span class="stat-reading" role="img">
|
|
153
|
+
<span class="stat-bar"><span class="stat-fill"></span></span>
|
|
154
|
+
<span class="stat-value"></span>
|
|
155
|
+
<span class="stat-note"></span>
|
|
156
|
+
</span>
|
|
157
|
+
</div>
|
|
158
|
+
</template>
|
|
159
|
+
|
|
160
|
+
<template id="model-template">
|
|
161
|
+
<section class="model">
|
|
162
|
+
<h3 class="model-head">
|
|
163
|
+
<button class="model-toggle" type="button" aria-expanded="false">
|
|
164
|
+
<span class="model-title"><span class="model-name"></span></span>
|
|
165
|
+
</button>
|
|
166
|
+
</h3>
|
|
167
|
+
<div class="model-detail" hidden></div>
|
|
168
|
+
</section>
|
|
169
|
+
</template>
|
|
170
|
+
|
|
123
171
|
<template id="session-template">
|
|
124
172
|
<article class="session-card" role="listitem" tabindex="0">
|
|
125
173
|
<span class="level-badge" aria-hidden="true"></span>
|
|
@@ -129,7 +177,7 @@
|
|
|
129
177
|
<div class="name"></div>
|
|
130
178
|
<div class="meta"></div>
|
|
131
179
|
</div>
|
|
132
|
-
<
|
|
180
|
+
<button class="model-pill" type="button"></button>
|
|
133
181
|
<span class="status-pill"></span>
|
|
134
182
|
</div>
|
|
135
183
|
<div class="cwd-line"></div>
|
package/web/styles.css
CHANGED
|
@@ -18,21 +18,20 @@
|
|
|
18
18
|
color-scheme: light;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
21
|
+
/* theme.js sets data-theme from the saved choice or the system setting before the first paint. */
|
|
22
|
+
:root[data-theme="dark"] {
|
|
23
|
+
--bg: #0f1115;
|
|
24
|
+
--surface: #171a21;
|
|
25
|
+
--surface-2: #1e222b;
|
|
26
|
+
--border: #2a303b;
|
|
27
|
+
--text: #e6e9ef;
|
|
28
|
+
--muted: #9aa4b2;
|
|
29
|
+
--accent: #7c7cf0;
|
|
30
|
+
--danger: #ef6b66;
|
|
31
|
+
--ok: #4cc38a;
|
|
32
|
+
--warn: #e0a84a;
|
|
33
|
+
--shadow: none;
|
|
34
|
+
color-scheme: dark;
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
* { box-sizing: border-box; }
|
|
@@ -69,7 +68,7 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; display: grid
|
|
|
69
68
|
|
|
70
69
|
.providers { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; }
|
|
71
70
|
.provider {
|
|
72
|
-
display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 10px 12px; padding: 14px;
|
|
71
|
+
display: grid; grid-template-columns: auto 1fr; align-items: center; align-content: start; gap: 10px 12px; padding: 14px;
|
|
73
72
|
border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); box-shadow: var(--shadow);
|
|
74
73
|
}
|
|
75
74
|
.provider.unavailable .provider-icon { filter: grayscale(1); opacity: 0.45; }
|
|
@@ -86,6 +85,16 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; display: grid
|
|
|
86
85
|
.provider .state.update-available { color: var(--warn); }
|
|
87
86
|
.provider.unavailable .state { color: var(--muted); }
|
|
88
87
|
.provider .update { color: var(--warn); border-color: var(--warn); }
|
|
88
|
+
.provider .accounts { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 6px; }
|
|
89
|
+
.account-chip {
|
|
90
|
+
font: inherit; font-size: 0.75rem; font-weight: 600; padding: 2px 10px; border-radius: 999px; cursor: pointer;
|
|
91
|
+
border: 1px solid var(--border); background: var(--surface-2); color: var(--muted); max-width: 100%;
|
|
92
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
93
|
+
}
|
|
94
|
+
.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); }
|
|
97
|
+
.account-chip.unsigned { border-style: dashed; }
|
|
89
98
|
.provider .usage { grid-column: 1 / -1; display: grid; gap: 4px; }
|
|
90
99
|
.provider .usage:empty { display: none; }
|
|
91
100
|
.meter { display: grid; grid-template-columns: 5.5em 1fr auto; align-items: center; gap: 8px; font-size: 0.75rem; color: var(--muted); }
|
|
@@ -96,6 +105,69 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; display: grid
|
|
|
96
105
|
.meter.empty .meter-fill { background: var(--danger); }
|
|
97
106
|
.meter-value { white-space: nowrap; font-variant-numeric: tabular-nums; }
|
|
98
107
|
.usage-note { font-size: 0.75rem; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
108
|
+
.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;
|
|
110
|
+
}
|
|
111
|
+
.provider .model-stats:empty { display: none; }
|
|
112
|
+
.provider .model-stats > .usage-note { grid-column: 1 / -1; contain: inline-size; }
|
|
113
|
+
.model-stats-head {
|
|
114
|
+
grid-column: 1 / -1; justify-self: start; max-width: 100%; min-height: 24px; padding: 0; border: 0; background: none; color: var(--accent);
|
|
115
|
+
font: inherit; font-size: 0.78rem; text-align: left; cursor: pointer;
|
|
116
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
117
|
+
}
|
|
118
|
+
.model-stats-head::after { content: " ›"; }
|
|
119
|
+
.model-stats-head:hover { text-decoration: underline; }
|
|
120
|
+
.model-stats-head:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
|
|
121
|
+
|
|
122
|
+
.stat {
|
|
123
|
+
--tier: var(--border);
|
|
124
|
+
grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; align-items: center;
|
|
125
|
+
min-height: 24px; font-size: 0.75rem; color: var(--muted);
|
|
126
|
+
}
|
|
127
|
+
.stat-label { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
|
|
128
|
+
.stat-reading { grid-column: 2 / -1; display: grid; grid-template-columns: subgrid; align-items: center; }
|
|
129
|
+
.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;
|
|
133
|
+
}
|
|
134
|
+
.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; }
|
|
137
|
+
.tip {
|
|
138
|
+
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);
|
|
140
|
+
font-size: 0.78rem; line-height: 1.45; pointer-events: none;
|
|
141
|
+
}
|
|
142
|
+
.tip strong { font-weight: 600; }
|
|
143
|
+
.tip span { margin-left: 6px; font-size: 0.72rem; opacity: 0.75; }
|
|
144
|
+
.tip span::before { content: "· "; }
|
|
145
|
+
.tip p { margin: 4px 0 0; }
|
|
146
|
+
.stat-bar { height: 6px; border-radius: 3px; background: var(--surface-2); overflow: hidden; }
|
|
147
|
+
.stat-fill { display: block; width: 0; height: 100%; border-radius: 3px; background: var(--tier); }
|
|
148
|
+
.stat-value, .model-index { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--text); }
|
|
149
|
+
.stat-value { justify-content: flex-end; }
|
|
150
|
+
.stat-value .level, .model-index .level { min-width: 3ch; text-align: right; }
|
|
151
|
+
.stat.unmeasured .stat-value, .model-index.unmeasured { color: var(--muted); }
|
|
152
|
+
.stat-note { display: none; }
|
|
153
|
+
.stat-tier {
|
|
154
|
+
display: inline-grid; place-items: center; width: 1.7em; height: 1.7em; border-radius: 4px;
|
|
155
|
+
font-size: 0.68rem; font-weight: 700; line-height: 1;
|
|
156
|
+
color: var(--tier-ink); background: color-mix(in srgb, var(--tier) 16%, var(--surface));
|
|
157
|
+
border: 1px solid color-mix(in srgb, var(--tier) 50%, transparent);
|
|
158
|
+
}
|
|
159
|
+
.tier-s { --tier: #c99a2e; --tier-ink: #7a5200; }
|
|
160
|
+
.tier-a { --tier: #8b5cf6; --tier-ink: #5b21b6; }
|
|
161
|
+
.tier-b { --tier: #3b82f6; --tier-ink: #1d4ed8; }
|
|
162
|
+
.tier-c { --tier: #22a35a; --tier-ink: #166534; }
|
|
163
|
+
.tier-d { --tier: #94a3b8; --tier-ink: #475569; }
|
|
164
|
+
:where(:root[data-theme="dark"]) {
|
|
165
|
+
.tier-s { --tier: #e0b45c; --tier-ink: #f6dea6; }
|
|
166
|
+
.tier-a { --tier: #a78bfa; --tier-ink: #ddd3ff; }
|
|
167
|
+
.tier-b { --tier: #60a5fa; --tier-ink: #cfe3ff; }
|
|
168
|
+
.tier-c { --tier: #4ade80; --tier-ink: #c6f6d5; }
|
|
169
|
+
.tier-d { --tier: #94a3b8; --tier-ink: #d4dbe4; }
|
|
170
|
+
}
|
|
99
171
|
.provider-links { grid-column: 1 / -1; display: flex; gap: 14px; font-size: 0.78rem; }
|
|
100
172
|
.console-link { color: var(--accent); text-decoration: none; }
|
|
101
173
|
.console-link:hover { text-decoration: underline; }
|
|
@@ -139,7 +211,10 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; display: grid
|
|
|
139
211
|
font-size: 0.72rem; font-weight: 600; padding: 3px 8px; border-radius: 999px; white-space: nowrap;
|
|
140
212
|
max-width: 11em; overflow: hidden; text-overflow: ellipsis;
|
|
141
213
|
background: color-mix(in srgb, var(--accent) 14%, var(--surface)); color: var(--accent);
|
|
214
|
+
border: 0; font-family: inherit; cursor: pointer;
|
|
142
215
|
}
|
|
216
|
+
.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; }
|
|
143
218
|
.model-pill.screen { font-weight: 500; }
|
|
144
219
|
.status-pill.active { color: var(--ok); }
|
|
145
220
|
.status-pill.active::before { content: "● "; animation: pulse 1.2s ease-in-out infinite; }
|
|
@@ -174,7 +249,9 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; display: grid
|
|
|
174
249
|
.btn.danger { color: var(--danger); }
|
|
175
250
|
.btn.danger:hover { border-color: var(--danger); }
|
|
176
251
|
.btn:disabled { opacity: 0.6; cursor: progress; }
|
|
177
|
-
.stop-manager { white-space: nowrap; }
|
|
252
|
+
.stop-manager, .theme-toggle, .upgrade { white-space: nowrap; }
|
|
253
|
+
.btn.upgrade { color: var(--warn); border-color: var(--warn); }
|
|
254
|
+
.upgrade-note { font-size: 0.85rem; color: var(--warn); }
|
|
178
255
|
|
|
179
256
|
.empty { color: var(--muted); margin: 8px 0 0; }
|
|
180
257
|
|
|
@@ -203,6 +280,67 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; display: grid
|
|
|
203
280
|
.terminal-host { flex: 1; min-height: 0; padding: 8px 4px 4px 10px; }
|
|
204
281
|
.terminal-host > div { height: 100%; }
|
|
205
282
|
|
|
283
|
+
.models {
|
|
284
|
+
width: min(880px, calc(100vw - 32px)); max-height: calc(100vh - 48px); padding: 0; overflow: hidden;
|
|
285
|
+
border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); color: var(--text);
|
|
286
|
+
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.35);
|
|
287
|
+
}
|
|
288
|
+
.models[open] { display: flex; flex-direction: column; }
|
|
289
|
+
.models::backdrop { background: rgba(15, 17, 21, 0.5); }
|
|
290
|
+
.models-bar { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--border); }
|
|
291
|
+
.models-heading { flex: 1; min-width: 0; }
|
|
292
|
+
.models-heading .sub { margin: 2px 0 0; color: var(--muted); font-size: 0.78rem; }
|
|
293
|
+
.models-body { flex: 1; min-height: 0; overflow: auto; padding: 0 14px 14px; }
|
|
294
|
+
.model-columns, .model-toggle { display: grid; grid-template-columns: minmax(0, 1fr) repeat(3, 6.5rem) 4.5rem; align-items: center; gap: 8px; }
|
|
295
|
+
.model-columns {
|
|
296
|
+
position: sticky; top: 0; z-index: 1; padding: 10px 8px 6px; background: var(--surface);
|
|
297
|
+
border-bottom: 1px solid var(--border); color: var(--muted); font-size: 0.72rem; font-weight: 600;
|
|
298
|
+
}
|
|
299
|
+
.model-columns span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
300
|
+
.model-columns span:last-child, .model-context { text-align: right; }
|
|
301
|
+
.model { border-bottom: 1px solid var(--border); }
|
|
302
|
+
.model-head { margin: 0; font: inherit; }
|
|
303
|
+
.model-toggle {
|
|
304
|
+
width: 100%; padding: 9px 8px; border: 0; border-radius: 6px; background: none; color: var(--text);
|
|
305
|
+
font: inherit; font-size: 0.85rem; text-align: left; cursor: pointer;
|
|
306
|
+
}
|
|
307
|
+
.model-toggle:hover { background: var(--surface-2); }
|
|
308
|
+
.model-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
|
|
309
|
+
.model-title { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; min-width: 0; }
|
|
310
|
+
.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; }
|
|
312
|
+
.model-toggle[aria-expanded="true"] .model-name::before { transform: rotate(90deg); }
|
|
313
|
+
.model-context { color: var(--muted); font-variant-numeric: tabular-nums; }
|
|
314
|
+
.badge {
|
|
315
|
+
font-size: 0.66rem; font-weight: 600; padding: 1px 7px; border-radius: 999px; white-space: nowrap;
|
|
316
|
+
background: var(--surface-2); color: var(--muted); border: 1px solid var(--border);
|
|
317
|
+
}
|
|
318
|
+
.badge.in-use { --badge: var(--accent); color: color-mix(in srgb, var(--badge) 80%, #000); }
|
|
319
|
+
.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); }
|
|
322
|
+
:where(:root[data-theme="dark"]) {
|
|
323
|
+
.badge.in-use, .badge.new, .badge.expires { color: var(--badge); }
|
|
324
|
+
}
|
|
325
|
+
.model-detail {
|
|
326
|
+
display: grid; grid-template-columns: max-content minmax(48px, 1fr) auto minmax(0, 19em); gap: 14px 10px;
|
|
327
|
+
padding: 4px 8px 16px calc(8px + 1em);
|
|
328
|
+
}
|
|
329
|
+
.model-group { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; align-items: center; row-gap: 2px; }
|
|
330
|
+
.model-group h4, .model-none { grid-column: 1 / -1; }
|
|
331
|
+
.model-group h4 { margin: 0 0 2px; font-size: 0.7rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); }
|
|
332
|
+
.model-detail .stat-note { display: block; font-size: 0.72rem; }
|
|
333
|
+
.model-detail .stat-fill { transform-origin: left; animation: stat-fill 0.45s ease-out; }
|
|
334
|
+
.model-none { margin: 0; font-size: 0.75rem; color: var(--muted); }
|
|
335
|
+
.model-more { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 6px 16px; font-size: 0.78rem; }
|
|
336
|
+
.model-facts { display: flex; flex-wrap: wrap; gap: 4px 16px; margin: 0; }
|
|
337
|
+
.model-facts div { display: flex; gap: 6px; }
|
|
338
|
+
.model-facts dt { color: var(--muted); }
|
|
339
|
+
.model-facts dd { margin: 0; }
|
|
340
|
+
.models-more { margin-top: 12px; }
|
|
341
|
+
.models-note { margin: 14px 0 0; color: var(--muted); }
|
|
342
|
+
.models-source { margin: 0; padding: 10px 14px; border-top: 1px solid var(--border); color: var(--muted); font-size: 0.75rem; line-height: 1.45; }
|
|
343
|
+
|
|
206
344
|
.toast {
|
|
207
345
|
position: fixed; left: 50%; bottom: 20px; transform: translateX(-50%); z-index: 20;
|
|
208
346
|
max-width: min(640px, calc(100vw - 32px)); padding: 10px 14px; border-radius: 8px;
|
|
@@ -211,9 +349,11 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; display: grid
|
|
|
211
349
|
|
|
212
350
|
@keyframes pulse { 50% { opacity: 0.35; } }
|
|
213
351
|
@keyframes ring { 0% { transform: scale(0.85); opacity: 0.8; } 100% { transform: scale(1.3); opacity: 0; } }
|
|
352
|
+
@keyframes stat-fill { from { transform: scaleX(0); } }
|
|
214
353
|
|
|
215
354
|
@media (prefers-reduced-motion: reduce) {
|
|
216
|
-
.status-pill.active::before, .agent.working::after { animation: none; }
|
|
355
|
+
.status-pill.active::before, .agent.working::after, .model-detail .stat-fill { animation: none; }
|
|
356
|
+
.model-name::before { transition: none; }
|
|
217
357
|
}
|
|
218
358
|
|
|
219
359
|
@media (max-width: 640px) {
|
|
@@ -223,4 +363,11 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; display: grid
|
|
|
223
363
|
.terminal-panel { inset: var(--topbar-h, 56px) 0 0; border-radius: 0; }
|
|
224
364
|
.session-grid { grid-template-columns: 1fr; }
|
|
225
365
|
.cwd { flex-basis: 100%; }
|
|
366
|
+
.models { width: 100vw; max-width: 100vw; height: 100dvh; max-height: 100dvh; margin: 0; border-radius: 0; }
|
|
367
|
+
.model-columns, .model-toggle { grid-template-columns: minmax(0, 1fr) repeat(3, 4.6rem); }
|
|
368
|
+
.model-columns span:last-child, .model-context { display: none; }
|
|
369
|
+
.model-detail { padding-left: 8px; grid-template-columns: max-content minmax(32px, 1fr) auto; }
|
|
370
|
+
.model-detail .stat { padding-bottom: 6px; }
|
|
371
|
+
.model-detail .stat-reading { row-gap: 1px; }
|
|
372
|
+
.model-detail .stat-note { grid-column: 1 / -1; }
|
|
226
373
|
}
|
package/web/theme.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Applies the chosen theme before the first paint, so the page never flashes
|
|
2
|
+
// the other one. Loaded in <head> as a plain script; app.js owns the toggle.
|
|
3
|
+
(function () {
|
|
4
|
+
var theme = null;
|
|
5
|
+
try { theme = localStorage.getItem('agentGuild.theme'); } catch (e) { /* storage unavailable */ }
|
|
6
|
+
if (theme !== 'light' && theme !== 'dark') {
|
|
7
|
+
theme = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
8
|
+
}
|
|
9
|
+
document.documentElement.dataset.theme = theme;
|
|
10
|
+
})();
|