agentgui 1.0.1004 → 1.0.1006

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 CHANGED
@@ -1,5 +1,9 @@
1
1
  # AgentGUI — Agent Notes
2
2
 
3
+ ## GUI perceived-performance sweep (2026-07-02) — twenty-third run
4
+
5
+ Small, targeted run landing the 22nd-run's deferred perceived-perf findings. `index.html` now `modulepreload`s the marked/dompurify ESM CDN modules (was preconnect-only) so the fetch starts in parallel with the kit/app module graph instead of waiting for `markdown.js`'s dynamic import on the first chat response's escaped-text-to-rendered-markdown swap. Settings server panel shows "checking…" instead of "unknown" for version/uptime/clients/projects-folder during the very first health probe (new `state.healthChecking` flag around `recheckHealth`'s await — "unknown" reads as a permanent broken-server fact, not in-flight loading). Settings agents panel title shows "agents · loading…" instead of the literal "agents · 0/0 installed" while the initial fetch is in flight. Still deferred (its own PRD row, re-scoped not dropped): first-render network-gating — the shell paints nothing between the boot-splash and health-probe completion, needing a render-architecture change (skeleton/optimistic shell) bigger than this run's slice. No kit changes this run. agentgui pushed `6a045ba`, 28/28 tests, 0 console errors.
6
+
3
7
  ## GUI ux-craft sweep (2026-07-02) — twenty-second run
4
8
 
5
9
  `gui-ux-craft` workflow wf_48cd6bae-6ae (35 agents, 20 confirmed). Kit (`../design`): **accent-on-paper contrast fix** — `var(--accent)` (lime, fill-only per its own token comment) was used directly as TEXT color in 7 sites and as a non-text FILL in 3 more (the live status dot, green session-rail fill), rendering ~1.07:1 contrast on the paper theme (WCAG needs 4.5:1 text / 3:1 non-text). Swapped all 10 to `--accent-ink`; borders/outlines/box-shadows on the same rules stayed on `--accent` (already non-text-passing). Four typography-rhythm fixes: `.ds-dash-title` now matches `.ds-session-title` size (was one step larger despite a comment claiming parity), `ContextPane` Row meta/sub now match the kit-wide Row default size (were one step smaller, `.sub` also dropped an unwanted forced monospace), `.ds-session-group-label` now matches `.panel-head`/`table th` sizing, `.ws-crumb` height now derives from `--app-crumb-h` instead of an unlinked magic number. Session rail's new-chat button and search input now share a 36px desktop height. `.ds-file-act` gained an explicit `:focus-visible` ring (was the only icon/toolbar-button family without one).
@@ -109,7 +113,7 @@ Shipped the three-column **WorkspaceShell** + **WorkspaceRail** (kit `shell.js`,
109
113
 
110
114
  ## GUI-predictability sweep closure (2026-06-05) — third maximum-effort run
111
115
 
112
- Fan-out reviewers (chat/history/settings/shell + perf/security/glyph/override) -> adversarial verify -> 19 PRD rows fixed+pushed: agentgui `fe94ade`, kit `anentrypoint-design` `236d6ef` (publish.yml -> npm/unpkg). The headline theme was **override-elimination**: index.html's `!important` overrides were converted to kit defaults (Topbar active-tab = tinted+underline; `PageHeader` `compact` prop -> `.ds-section-compact` margin-top:0; `Row` `cursor:pointer` for `role=button`/`a.row`; kit `Chat` dropped the decorative head `.dot`). Also: kit `ToolCallNode` `(no output)` placeholder for done+empty tools; kit `safeUrl()` rejects `javascript:`/`data:`/`file:` in `renderInline`/image/link parts (inline renderer bypasses DOMPurify); streaming chat text uses the `.chat-md` container to avoid settle reflow. App reconciliation/state fixes (distinct backend-status keys, per-sid running-dot key, stale-selectedSid clear, per-session live counter, toolLabel scalar fallback, expand/collapse-**shown** relabel, projectFilter cleared on search). `.claude/workflows/gui-audit.js` gained an `overrides` surface + a **KEPT-SET glyph guard** in both the reviewer and the adversarial verifier (the middot/ellipsis/em-dash are kept product typography — never flag them). Detail + the kit dist `git add -f` / rebase-rebuild caveat in rs-learn (recall "agentgui GUI-predictability sweep"). **index.html loads the kit from LOCAL `./vendor/anentrypoint-design/247420.{js,css}`** — the vendored copy IS what ships; update flow is edit kit -> `node scripts/build.mjs` -> copy dist into vendor -> browser-witness -> push kit.
116
+ Override-elimination pass (index.html `!important` -> kit defaults) + 19 other PRD rows. Full detail in rs-learn (recall "agentgui 3rd run GUI-predictability sweep closure").
113
117
 
114
118
  ## GUI-audit closure (2026-06-04 fan-out) — second maximum-effort sweep
115
119
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentgui",
3
- "version": "1.0.1004",
3
+ "version": "1.0.1006",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "electron/main.js",
@@ -37,6 +37,13 @@
37
37
  <link rel="modulepreload" href="./js/backend.js">
38
38
  <link rel="modulepreload" href="./js/codec.js">
39
39
  <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin>
40
+ <!-- Preconnect alone still leaves the marked/dompurify ESM fetch+parse as a
41
+ full round trip AFTER the kit loads, on the first chat markdown render
42
+ (escaped-text -> rendered-markdown swap). modulepreload starts that
43
+ fetch in parallel with everything else instead of waiting for
44
+ markdown.js to reach its dynamic import. -->
45
+ <link rel="modulepreload" href="https://cdn.jsdelivr.net/npm/marked@15.0.12/+esm" crossorigin>
46
+ <link rel="modulepreload" href="https://cdn.jsdelivr.net/npm/dompurify@3.2.6/+esm" crossorigin>
40
47
  <!-- No design content lives here. Every agentgui application-surface style
41
48
  (pills, cwd bar, resume banner, health chips, settings grid, history
42
49
  empty state, boot splash, scrollbar theming, focus rings, print) now
@@ -3075,14 +3075,18 @@ function serverPanel() {
3075
3075
  const roots = Array.isArray(hh.allowRoots) ? hh.allowRoots : [];
3076
3076
  const upMs = hh.uptimeMs != null ? hh.uptimeMs : (hh.uptime != null ? hh.uptime * 1000 : null);
3077
3077
  const wsClients = hh.wsClients != null ? hh.wsClients : (hh.clients != null ? hh.clients : null);
3078
+ // The very first health probe is in flight (not yet failed, not yet
3079
+ // succeeded): 'checking…' reads as progress, 'unknown' reads as a
3080
+ // permanent fact about the server - only the first is true here.
3081
+ const fallback = (hh.status === 'unknown' && state.healthChecking) ? 'checking…' : 'unknown';
3078
3082
  return Panel({
3079
3083
  id: 'server',
3080
3084
  title: 'server',
3081
3085
  children: [
3082
- h('div', { key: 'sv', class: 'lede' }, 'version: ' + (hh.version ? 'v' + hh.version : 'unknown')),
3083
- h('div', { key: 'sup', class: 'lede' }, 'uptime: ' + (upMs != null ? fmtDuration(upMs) : 'unknown')),
3084
- h('div', { key: 'swc', class: 'lede' }, 'connected clients: ' + (wsClients != null ? wsClients : 'unknown')),
3085
- h('div', { key: 'spd', class: 'lede' }, 'projects folder: ' + (hh.projectsDir || 'unknown')),
3086
+ h('div', { key: 'sv', class: 'lede' }, 'version: ' + (hh.version ? 'v' + hh.version : fallback)),
3087
+ h('div', { key: 'sup', class: 'lede' }, 'uptime: ' + (upMs != null ? fmtDuration(upMs) : fallback)),
3088
+ h('div', { key: 'swc', class: 'lede' }, 'connected clients: ' + (wsClients != null ? wsClients : fallback)),
3089
+ h('div', { key: 'spd', class: 'lede' }, 'projects folder: ' + (hh.projectsDir || fallback)),
3086
3090
  roots.length
3087
3091
  ? SessionMeta({ key: 'sroots', items: roots.map((r, i) => ({ label: 'root ' + (i + 1), value: r, title: r, onCopy: () => copyText(r, 'root copied') })) })
3088
3092
  : (hh.status && hh.status !== 'unknown' ? h('div', { key: 'snoroots', class: 'lede' }, 'allowed roots: none configured') : null),
@@ -3163,9 +3167,14 @@ function acpStatusFor(agentId) {
3163
3167
  function agentsPanel() {
3164
3168
  const installed = state.agents.filter(a => a.available !== false);
3165
3169
  const hasAcp = (Array.isArray(state.health.acp) ? state.health.acp : []).length > 0;
3170
+ // '0/0 installed' during the initial fetch reads as "nothing works", not
3171
+ // "still loading" - show the loading word instead until the list lands.
3172
+ const title = (state.agentsLoading && !state.agents.length)
3173
+ ? 'agents · loading…'
3174
+ : 'agents · ' + installed.length + '/' + state.agents.length + ' installed';
3166
3175
  return Panel({
3167
3176
  id: 'agents',
3168
- title: 'agents · ' + installed.length + '/' + state.agents.length + ' installed',
3177
+ title,
3169
3178
  children: [
3170
3179
  // ACP agents (opencode/kilo/codex) are managed automatically: started
3171
3180
  // on-demand and restarted with backoff by the server, so there are no
@@ -3439,7 +3448,13 @@ function startHealthPolling() {
3439
3448
  }
3440
3449
  async function recheckHealth() {
3441
3450
  const wasOk = state.health.status === 'ok';
3451
+ // Distinguishes "never probed yet" (status stays 'unknown', server panel
3452
+ // shows literal 'unknown' fields with no affordance) from "probe in
3453
+ // flight" - the settings server panel reads this to show 'checking…'
3454
+ // instead of a wall of 'unknown' during the very first health probe.
3455
+ state.healthChecking = true;
3442
3456
  const r = await B.probeBackend(state.backend);
3457
+ state.healthChecking = false;
3443
3458
  if (r.ok) {
3444
3459
  state.health = { status: 'ok', ...r.info };
3445
3460
  stopHealthPolling();