agentgui 1.0.940 → 1.0.942
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/AGENTS.md +6 -7
- package/package.json +1 -1
- package/server.js +10 -1
- package/site/app/index.html +129 -38
- package/site/app/js/app.js +302 -72
- package/site/app/js/backend.js +20 -10
- package/site/app/vendor/anentrypoint-design/247420.css +274 -86
- package/site/app/vendor/anentrypoint-design/247420.js +13 -13
package/AGENTS.md
CHANGED
|
@@ -16,14 +16,9 @@ Dependencies:
|
|
|
16
16
|
- `ccsniff` (>=1.1.0) — exports `createHistoryRouter({projectsDir})` mountable on Express; serves `/v1/history/{sessions,sessions/:sid/events,search,snapshot,reindex,stream}`. Reads `~/.claude/projects` (override via `CLAUDE_PROJECTS_DIR`).
|
|
17
17
|
- `anentrypoint-design` (>=0.0.119) — kit library, single-file ESM from unpkg
|
|
18
18
|
|
|
19
|
-
## Browser Witness
|
|
19
|
+
## Browser Witness
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
- `GET /health` → 200 JSON
|
|
23
|
-
- `GET /v1/history/sessions` → `{"sessions":[]}` from ccsniff
|
|
24
|
-
- `GET /` → site/app/index.html
|
|
25
|
-
- WS `/sync` → opens, sync_connected
|
|
26
|
-
- Browser at `localhost:3056/`: AppShell renders, nav=[chat,history,settings], SSE `hello` received (live.connected=true, eventCount=1), 0 console errors, backend resolves to `''` (same origin).
|
|
21
|
+
`bun server.js`. Default `PORT=3000` (server.js); the SPA is served under `BASE_URL` (default `/gm/`), so the live app is **http://localhost:3000/gm/** — `/health` and `/` answer at root, the app is under `/gm/`. First request to `/gm/` or `/v1/history/*` triggers a 30-90s ccsniff JSONL walk (curl with a short timeout returns 000 during warmup). AppShell renders nav=[chat,history,settings], SSE `hello`, 0 console errors, backend resolves to `''` (same origin).
|
|
27
22
|
|
|
28
23
|
## Learning audit
|
|
29
24
|
|
|
@@ -149,3 +144,7 @@ The GUI runs fully offline. `site/app/vendor/cdn/` holds marked, dompurify, pris
|
|
|
149
144
|
- `agents.list` (WS) returns `available` + `npxInstallable` per agent; `agents.models` returns model choices (claude-code → sonnet/opus/haiku). The chat picker is **agent-then-model**, not a flat model list. Unavailable agents are disabled/gated.
|
|
150
145
|
- `chat.sendMessage` accepts `cwd` (defaults to STARTUP_CWD) and `model`/`agentId` separately. `chat.active` (WS) lists in-flight chats with agentId/model/cwd/startedAt/pid; the history tab polls it (3s) and shows a running panel with per-session stop.
|
|
151
146
|
- Client (`app.js`): chat transcript persists to `localStorage[agentgui.chat]` and restores on load; tool_use/result events render as chat parts; keyboard shortcuts (g+c/h/s, n, /, ?); settings has an agents-status panel from `health.acp[]`.
|
|
147
|
+
|
|
148
|
+
## DS CSS cascade — overriding component styles (2026-05-28)
|
|
149
|
+
|
|
150
|
+
**`installStyles()` injects DS CSS into a runtime `<style>` after the head `<style>`, so local overrides need `!important` or higher specificity than the DS's `.ds-247420`-prefixed rules.** Full detail (font vars `--ff-display`/`--ff-mono`, the `.chat-head .sub` "00 msgs" quirk, EventList `.row[role=button]`, `[data-prog-focus]` focus suppression, `projectLabel()` for cwd slugs) is in rs-learn (recall "agentgui GUI styling DS cascade installStyles").
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -173,9 +173,18 @@ const onServerListenStart = () => {
|
|
|
173
173
|
loadPluginExtensions();
|
|
174
174
|
};
|
|
175
175
|
|
|
176
|
+
let _portRetries = 0;
|
|
177
|
+
const MAX_PORT_RETRIES = 5;
|
|
176
178
|
server.on('error', (err) => {
|
|
177
179
|
if (err.code === 'EADDRINUSE') {
|
|
178
|
-
|
|
180
|
+
_portRetries++;
|
|
181
|
+
if (_portRetries > MAX_PORT_RETRIES) {
|
|
182
|
+
// Bail instead of retrying forever — an unbounded retry loop leaks a
|
|
183
|
+
// live process that holds no useful port and accumulates on each launch.
|
|
184
|
+
console.error(`Port ${PORT} still in use after ${MAX_PORT_RETRIES} retries; exiting. Free the port or set PORT to a different value.`);
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
187
|
+
console.error(`Port ${PORT} already in use. Retry ${_portRetries}/${MAX_PORT_RETRIES} in 3s...`);
|
|
179
188
|
setTimeout(() => { server.listen(PORT, onServerListenStart); }, 3000);
|
|
180
189
|
} else {
|
|
181
190
|
console.error('[SERVER] Error (contained):', err.message);
|
package/site/app/index.html
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
|
-
<html lang="en" class="ds-247420" data-theme="dark">
|
|
2
|
+
<html lang="en" class="ds-247420" data-theme="dark" data-typescale="app">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
@@ -21,11 +21,39 @@
|
|
|
21
21
|
height: 100%;
|
|
22
22
|
background: var(--bg, var(--agentgui-bg));
|
|
23
23
|
color: var(--fg, var(--agentgui-fg));
|
|
24
|
-
|
|
24
|
+
/* The DS exposes --ff-display / --ff-mono (there is no --font-sans), so the
|
|
25
|
+
old reference fell through to the system font. Use the DS display face. */
|
|
26
|
+
font-family: var(--ff-display, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif);
|
|
25
27
|
}
|
|
26
28
|
#app { height: 100vh; height: 100dvh; }
|
|
27
29
|
#app > * { height: 100%; }
|
|
28
30
|
|
|
31
|
+
/* Themed thin scrollbars — the native chrome scrollbar is chunky/light and
|
|
32
|
+
clashes with the dark theme on the history sidebar and settings column. */
|
|
33
|
+
* {
|
|
34
|
+
scrollbar-width: thin;
|
|
35
|
+
scrollbar-color: color-mix(in srgb, var(--fg, var(--agentgui-fg)) 22%, transparent) transparent;
|
|
36
|
+
}
|
|
37
|
+
*::-webkit-scrollbar { width: 9px; height: 9px; }
|
|
38
|
+
*::-webkit-scrollbar-track { background: transparent; }
|
|
39
|
+
*::-webkit-scrollbar-thumb {
|
|
40
|
+
background: color-mix(in srgb, var(--fg, var(--agentgui-fg)) 20%, transparent);
|
|
41
|
+
border-radius: 999px;
|
|
42
|
+
border: 2px solid transparent;
|
|
43
|
+
background-clip: padding-box;
|
|
44
|
+
}
|
|
45
|
+
*::-webkit-scrollbar-thumb:hover {
|
|
46
|
+
background: color-mix(in srgb, var(--fg, var(--agentgui-fg)) 34%, transparent);
|
|
47
|
+
background-clip: padding-box;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* We move focus to the page heading on tab change for AT users; suppress the
|
|
51
|
+
resulting green outline box on those programmatically-focused elements.
|
|
52
|
+
!important + .ds-247420 prefix to beat the runtime-injected DS focus rule. */
|
|
53
|
+
.ds-247420 [data-prog-focus]:focus,
|
|
54
|
+
.ds-247420 [data-prog-focus]:focus-visible,
|
|
55
|
+
[data-prog-focus]:focus, [data-prog-focus]:focus-visible { outline: none !important; box-shadow: none !important; }
|
|
56
|
+
|
|
29
57
|
/* skip link for keyboard/AT users */
|
|
30
58
|
.skip-link {
|
|
31
59
|
position: absolute; left: -9999px; top: 0; z-index: 1000;
|
|
@@ -90,32 +118,17 @@
|
|
|
90
118
|
|
|
91
119
|
.field-error { color: var(--warn, var(--agentgui-warn)); }
|
|
92
120
|
|
|
93
|
-
/* chat control cluster in the crumb bar:
|
|
94
|
-
|
|
95
|
-
.chat-controls { display: flex; align-items: center; gap: .6em; flex-wrap:
|
|
121
|
+
/* chat control cluster in the crumb bar: model picker, +new, status.
|
|
122
|
+
Allowed to wrap so it never overflows the crumb on tablet widths. */
|
|
123
|
+
.chat-controls { display: flex; align-items: center; gap: .6em; flex-wrap: wrap; }
|
|
96
124
|
.chat-controls > * { flex: 0 0 auto; }
|
|
97
125
|
.chat-controls select,
|
|
98
126
|
.chat-controls .select,
|
|
99
|
-
.chat-controls [role="combobox"] { min-width:
|
|
127
|
+
.chat-controls [role="combobox"] { min-width: 130px; max-width: 220px; }
|
|
100
128
|
.chat-controls .status-dot { white-space: nowrap; }
|
|
101
129
|
|
|
102
|
-
/* Tame the design-system hero-sized PageHeader h1 to a sensible page title.
|
|
103
|
-
The DS default (--fs-h1, cqi-scaled to ~64-80px) overpowers app content. */
|
|
104
|
-
.agentgui-main .ds-section > h1 {
|
|
105
|
-
font-size: clamp(22px, 2.2vw, 30px);
|
|
106
|
-
line-height: 1.15;
|
|
107
|
-
margin-bottom: .35em;
|
|
108
|
-
}
|
|
109
130
|
.agentgui-main .ds-section { margin: 0 0 var(--space-4, 16px); }
|
|
110
131
|
|
|
111
|
-
/* TextField: stack label above the input so the label can't overlap it. */
|
|
112
|
-
.agentgui-main .ds-field {
|
|
113
|
-
display: flex; flex-direction: column; gap: .35em; align-items: stretch;
|
|
114
|
-
}
|
|
115
|
-
.agentgui-main .ds-field-label { font-size: .8rem; color: var(--fg-2, #ccc); }
|
|
116
|
-
.agentgui-main .ds-field input,
|
|
117
|
-
.agentgui-main .ds-field textarea { width: 100%; }
|
|
118
|
-
|
|
119
132
|
/* readable backend health summary (replaces raw JSON dump) */
|
|
120
133
|
.health-summary { display: flex; flex-wrap: wrap; gap: .4em; margin: .6em 0; }
|
|
121
134
|
.health-chip {
|
|
@@ -130,20 +143,8 @@
|
|
|
130
143
|
border-color: color-mix(in srgb, var(--accent, var(--agentgui-accent)) 40%, transparent);
|
|
131
144
|
}
|
|
132
145
|
|
|
133
|
-
/* search
|
|
134
|
-
|
|
135
|
-
.app .search-input input,
|
|
136
|
-
.app input.search,
|
|
137
|
-
input[type="search"] {
|
|
138
|
-
background: color-mix(in srgb, var(--fg, var(--agentgui-fg)) 6%, transparent);
|
|
139
|
-
color: var(--fg, var(--agentgui-fg));
|
|
140
|
-
border: 1px solid color-mix(in srgb, var(--fg, var(--agentgui-fg)) 16%, transparent);
|
|
141
|
-
border-radius: 8px; padding: .5em .7em;
|
|
142
|
-
}
|
|
143
|
-
.app input[type="search"]::placeholder { color: var(--fg-3, #888); }
|
|
144
|
-
.app input[type="search"]:focus-visible {
|
|
145
|
-
outline: 2px solid var(--accent, var(--agentgui-accent)); outline-offset: 1px;
|
|
146
|
-
}
|
|
146
|
+
/* (search-input theming now provided by the design system's .ds-search-input
|
|
147
|
+
+ base input rules; the local reskin hack was removed.) */
|
|
147
148
|
|
|
148
149
|
/* empty-state: keep it from wrapping awkwardly in the narrow sidebar */
|
|
149
150
|
.empty-state { white-space: normal; }
|
|
@@ -154,6 +155,92 @@
|
|
|
154
155
|
outline: 2px solid var(--accent, var(--agentgui-accent)); outline-offset: 2px;
|
|
155
156
|
}
|
|
156
157
|
|
|
158
|
+
/* Topbar nav: the DS renders the active tab as a large filled green pill that
|
|
159
|
+
sits taller than the inactive text links and reads as misaligned. Make all
|
|
160
|
+
tabs consistent — equal padding, the active one a subtle tinted underline-pill
|
|
161
|
+
rather than an oversized oval. */
|
|
162
|
+
/* Prefix with .ds-247420 (the <html> class) to match the DS selector's
|
|
163
|
+
specificity; source order then lets these win. */
|
|
164
|
+
.ds-247420 .app-topbar nav { display: flex; align-items: center; gap: .15em; }
|
|
165
|
+
.ds-247420 .app-topbar nav a {
|
|
166
|
+
padding: .35em .75em; border-radius: 8px; line-height: 1.4;
|
|
167
|
+
color: var(--fg-2, color-mix(in srgb, var(--fg, var(--agentgui-fg)) 75%, transparent));
|
|
168
|
+
text-decoration: none; background: transparent;
|
|
169
|
+
transition: background-color .15s ease, color .15s ease;
|
|
170
|
+
}
|
|
171
|
+
.ds-247420 .app-topbar nav a:hover { background: color-mix(in srgb, var(--fg, var(--agentgui-fg)) 8%, transparent); color: var(--fg, var(--agentgui-fg)); }
|
|
172
|
+
/* installStyles() injects the DS CSS into a runtime <style> appended after
|
|
173
|
+
this block, so equal-specificity rules lose on source order; !important is
|
|
174
|
+
the targeted override for the few props we reshape on the active tab. */
|
|
175
|
+
.ds-247420 .app-topbar nav a.active {
|
|
176
|
+
background: color-mix(in srgb, var(--accent, var(--agentgui-accent)) 16%, transparent) !important;
|
|
177
|
+
color: var(--accent, var(--agentgui-accent)) !important;
|
|
178
|
+
box-shadow: inset 0 -2px 0 0 var(--accent, var(--agentgui-accent)) !important;
|
|
179
|
+
border-radius: 8px !important;
|
|
180
|
+
font-weight: 600;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/* Compact working-directory bar (replaces the full-width tall banner box). */
|
|
184
|
+
.cwd-bar {
|
|
185
|
+
display: flex; align-items: center; gap: .5em; flex-wrap: wrap;
|
|
186
|
+
padding: .15em 0 .5em; font-size: .85rem;
|
|
187
|
+
}
|
|
188
|
+
.cwd-bar-text {
|
|
189
|
+
font-family: var(--ff-mono, ui-monospace, monospace);
|
|
190
|
+
color: var(--fg-3, #999); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 60vw;
|
|
191
|
+
}
|
|
192
|
+
.cwd-bar-btn {
|
|
193
|
+
cursor: pointer; font: inherit; line-height: 1.3;
|
|
194
|
+
padding: .15em .55em; border-radius: 6px;
|
|
195
|
+
background: color-mix(in srgb, var(--fg, var(--agentgui-fg)) 8%, transparent);
|
|
196
|
+
border: 1px solid color-mix(in srgb, var(--fg, var(--agentgui-fg)) 14%, transparent);
|
|
197
|
+
color: var(--fg-2, var(--agentgui-fg));
|
|
198
|
+
}
|
|
199
|
+
.cwd-bar-btn:hover { background: color-mix(in srgb, var(--fg, var(--agentgui-fg)) 14%, transparent); }
|
|
200
|
+
.cwd-bar-btn:focus-visible { outline: 2px solid var(--accent, var(--agentgui-accent)); outline-offset: 2px; }
|
|
201
|
+
|
|
202
|
+
/* History no-session empty state: fill the void with a centered prompt. */
|
|
203
|
+
.history-empty {
|
|
204
|
+
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
|
205
|
+
gap: .4em; text-align: center; min-height: 50vh; color: var(--fg-3, #888);
|
|
206
|
+
}
|
|
207
|
+
.history-empty-glyph { font-size: 3rem; opacity: .25; line-height: 1; }
|
|
208
|
+
.history-empty-title { margin: 0; font-size: 1.05rem; color: var(--fg-2, var(--agentgui-fg)); }
|
|
209
|
+
.history-empty-sub { margin: 0; max-width: 42ch; }
|
|
210
|
+
|
|
211
|
+
/* Settings: two-column on wide screens (backend + agents) so it uses the
|
|
212
|
+
full width instead of a cramped centered measure with empty margins. */
|
|
213
|
+
.settings-grid {
|
|
214
|
+
display: grid; gap: var(--space-4, 16px);
|
|
215
|
+
grid-template-columns: minmax(0, 1fr);
|
|
216
|
+
align-items: start;
|
|
217
|
+
}
|
|
218
|
+
@media (min-width: 900px) {
|
|
219
|
+
.settings-grid { grid-template-columns: minmax(0, 420px) minmax(0, 1fr); }
|
|
220
|
+
}
|
|
221
|
+
/* The DS PageHeader carries large vertical margins that leave a big empty
|
|
222
|
+
band above the heading and between the lede and the panels. Neutralize
|
|
223
|
+
them so settings/history read as normal top-aligned scrolling pages. */
|
|
224
|
+
.agentgui-main [class*="page-header"],
|
|
225
|
+
.agentgui-main .ds-page-header { margin-top: 0 !important; margin-bottom: var(--space-4, 16px) !important; }
|
|
226
|
+
.agentgui-main > :first-child { margin-top: 0 !important; }
|
|
227
|
+
.agentgui-main-settings .settings-grid { margin-top: 0; }
|
|
228
|
+
|
|
229
|
+
/* The DS Chat head computes its own zero-padded count ("00 msgs") and ignores
|
|
230
|
+
our sub prop; it reads as a bug. Hide the DS sub — streaming state shows via
|
|
231
|
+
the title and the busy banner. Also hide the DS's empty decorative head dot. */
|
|
232
|
+
.chat-head .sub { display: none; }
|
|
233
|
+
.chat-head .dot { display: none; }
|
|
234
|
+
|
|
235
|
+
/* EventList rows are role=button (click to expand) but the DS doesn't give
|
|
236
|
+
them a pointer cursor, so the affordance is invisible. */
|
|
237
|
+
.ds-event-list .row[role="button"] { cursor: pointer; }
|
|
238
|
+
.ds-event-list .row[role="button"]:hover { background: color-mix(in srgb, var(--fg, var(--agentgui-fg)) 5%, transparent); }
|
|
239
|
+
|
|
240
|
+
/* Chat composer: hide the idle scrollbar on the (empty/short) textarea. */
|
|
241
|
+
.chat-composer textarea { overflow-y: auto; scrollbar-width: thin; }
|
|
242
|
+
.chat-composer textarea:not(:focus) { overflow-y: hidden; }
|
|
243
|
+
|
|
157
244
|
/* touch targets on small screens */
|
|
158
245
|
@media (max-width: 640px) {
|
|
159
246
|
.pill { min-height: 36px; padding: .4em .8em; }
|
|
@@ -161,9 +248,13 @@
|
|
|
161
248
|
}
|
|
162
249
|
|
|
163
250
|
@media print {
|
|
164
|
-
#app { min-height: auto; display: block; }
|
|
165
|
-
.skip-link, .status-dot, .history-actions { display: none !important; }
|
|
166
|
-
|
|
251
|
+
#app { min-height: auto; display: block; height: auto; }
|
|
252
|
+
.skip-link, .status-dot, .history-actions, .chat-composer { display: none !important; }
|
|
253
|
+
/* Drop chrome backgrounds/shadows for ink-saving, but preserve code
|
|
254
|
+
highlighting and rail colors (don't nuke every color to black). */
|
|
255
|
+
.app, .app-main, .panel, .chat, .chat-thread {
|
|
256
|
+
background: #fff !important; color: #000 !important; box-shadow: none !important;
|
|
257
|
+
}
|
|
167
258
|
}
|
|
168
259
|
</style>
|
|
169
260
|
</head>
|