agentgui 1.0.973 → 1.0.974
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 +14 -6
- package/lib/http-handler.js +16 -4
- package/package.json +1 -1
- package/site/app/vendor/anentrypoint-design/247420.css +66 -22
- package/site/app/vendor/anentrypoint-design/247420.js +11 -11
- package/site/theme.mjs +2 -2
- package/scripts/harvest-fixtures.mjs +0 -219
- package/site/app/vendor/cdn/dompurify.js +0 -9
- package/site/app/vendor/cdn/fonts/1291de6d401a.woff2 +0 -0
- package/site/app/vendor/cdn/fonts/1ba89a87e0b8.woff2 +0 -0
- package/site/app/vendor/cdn/fonts/3644d51c507b.woff2 +0 -0
- package/site/app/vendor/cdn/fonts/4b91d2650dc2.woff2 +0 -0
- package/site/app/vendor/cdn/fonts/530d036ba64a.woff2 +0 -0
- package/site/app/vendor/cdn/fonts/570a2bdd8f8b.woff2 +0 -0
- package/site/app/vendor/cdn/fonts/5dd6d880fee9.woff2 +0 -0
- package/site/app/vendor/cdn/fonts/62de9143afe3.woff2 +0 -0
- package/site/app/vendor/cdn/fonts/64884efa2f11.woff2 +0 -0
- package/site/app/vendor/cdn/fonts/68cd7063be2e.woff2 +0 -0
- package/site/app/vendor/cdn/fonts/6c252abcf99b.woff2 +0 -0
- package/site/app/vendor/cdn/fonts/71e69e06516a.woff2 +0 -0
- package/site/app/vendor/cdn/fonts/9ea68c62083f.woff2 +0 -0
- package/site/app/vendor/cdn/fonts/c010f9b7d6b2.woff2 +0 -0
- package/site/app/vendor/cdn/fonts/d69723fc74be.woff2 +0 -0
- package/site/app/vendor/cdn/fonts/fonts.css +0 -459
- package/site/app/vendor/cdn/marked.js +0 -8
- package/site/app/vendor/cdn/prismjs/components/prism-bash.min.js +0 -1
- package/site/app/vendor/cdn/prismjs/components/prism-clike.min.js +0 -1
- package/site/app/vendor/cdn/prismjs/components/prism-core.min.js +0 -1
- package/site/app/vendor/cdn/prismjs/components/prism-css.min.js +0 -1
- package/site/app/vendor/cdn/prismjs/components/prism-diff.min.js +0 -1
- package/site/app/vendor/cdn/prismjs/components/prism-go.min.js +0 -1
- package/site/app/vendor/cdn/prismjs/components/prism-javascript.min.js +0 -1
- package/site/app/vendor/cdn/prismjs/components/prism-json.min.js +0 -1
- package/site/app/vendor/cdn/prismjs/components/prism-jsx.min.js +0 -1
- package/site/app/vendor/cdn/prismjs/components/prism-markdown.min.js +0 -1
- package/site/app/vendor/cdn/prismjs/components/prism-markup.min.js +0 -1
- package/site/app/vendor/cdn/prismjs/components/prism-python.min.js +0 -1
- package/site/app/vendor/cdn/prismjs/components/prism-rust.min.js +0 -1
- package/site/app/vendor/cdn/prismjs/components/prism-sql.min.js +0 -1
- package/site/app/vendor/cdn/prismjs/components/prism-toml.min.js +0 -1
- package/site/app/vendor/cdn/prismjs/components/prism-tsx.min.js +0 -1
- package/site/app/vendor/cdn/prismjs/components/prism-typescript.min.js +0 -1
- package/site/app/vendor/cdn/prismjs/components/prism-yaml.min.js +0 -1
package/AGENTS.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# AgentGUI — Agent Notes
|
|
2
2
|
|
|
3
|
+
## Design-maturity sweep + dead-code + secret-hardening (2026-06-18) — sixteenth run
|
|
4
|
+
|
|
5
|
+
Same mandate ("fix every aspect, all design lives in ../design, fan out subagents, track with a workflow"). One tracking Workflow **`gui-design-16` (run `wf_6479308b-24f`, 12 lenses chat-thread/composer-input/files-browser/sessions-dashboard/shell-chrome/tokens-theme/a11y-motion/history-settings/marketing-site/glyph-residue/dead-code/server-security): 54 agents -> hunt -> adversarial verify -> 40 confirmed findings, ~2.7M tokens.** Applied via a clean per-file subagent fan-out (one agent per physical file, zero edit conflicts).
|
|
6
|
+
|
|
7
|
+
**Kit fixes (ALL in `/config/workspace/design`):** chat.js ToolCallNode now gates the `args` section on real args (`hasArgs`) so result-only/arg-less cards no longer show `args {}` + composer `<textarea>` binds the `disabled` prop; agent-chat.js cwd input emits `aria-busy` while checking; content.js EventList now forwards `detail/actions/highlight/meta` to Row (expanded history events were dropping toolInput detail + copy + search-highlight) + TextField gained a full invalid/error state (`error`/`aria-invalid`/`aria-describedby`/`.ds-field-error` role=alert); interaction-primitives.js ShortcutList splits combos into discrete `.ds-kbd` caps (`.ds-kbd-caps`/`.ds-kbd-sep` + CSS) instead of one wide cap; sessions.js ConversationList rail filter migrated from bespoke `.ds-session-search` to the shared `SearchInput`/`.ds-search-input` (one filter control across rail + dashboard); shell.js WsResizer adds `aria-valuetext "<n> pixels"`; voice.js `×`->`Icon('x')`, community.js `⋯`->`'more'` (glyph residue). chat.css: cwd `.is-checking` hint tone + `aria-busy` field cue + cwd-btn `6px`->`var(--r-1)`, breakdown idle disc moved off the connecting-amber to canonical `--stale` double-inset, breakdown running disc shape-ring, `.ds-dash-clear` hover/focus-visible, `.chat-tool-copy:focus-visible`, errors-toggle AA fix, ds-session-search base block removed. app-shell.css: composer + WorkspaceShell (`.ws-rail/.ws-pane/.ws-sessions/.ws-scrim`) reduced-motion guards, `.ds-file-row.is-locked/.is-restricted` + `.ds-file-perm-tag` chip, `.ws-drawer-toggle` 44px coarse floor, `.ds-density-btn.active`/`.ds-filter-pill.active` AA contrast (`color:var(--fg)`), ShortcutList legend rules. editor-primitives.css `#000` dock shadow->`var(--shadow-3)` + checkbox `#fff` fallback dropped. app-surfaces.css `@media print` re-asserts paper-tuned signal tokens. community.css `:focus-visible` for ThreadPanel/Forum/Page + forum-search. marketing.css NEW `.site-footer` family (theme.mjs footers migrated off the in-app `.app-status` strip that suppressed content <=1100px) + `.site-cli` baseline+card-chrome + token paddings + `100dvh` embed.
|
|
8
|
+
|
|
9
|
+
**Server secret-hardening (`lib/http-handler.js`, the high-sev cluster):** the module-level `SECRET_RE` (already blocking `/api/file`+`/api/download`) is now ALSO applied to `/api/upload-file`, `/api/mkdir`, `/api/rename` (403 on a secret/dotfile target name — was an overwrite-a-secret hole) and `/api/list` (filters secret-named dirents from the listing — was enumerating `.env`/`.pem` the preview/download routes block); `/api/download` Content-Disposition is now RFC-5987 encoded (ASCII `filename=` fallback + `filename*=UTF-8''<pct>`) so a CJK/emoji name no longer throws `ERR_INVALID_CHAR`. `validate-mutations.mjs` 26/26 PASS, no regression.
|
|
10
|
+
|
|
11
|
+
**Dead-code removal:** agentgui `site/app/vendor/cdn/` (36 dead files — marked/dompurify/prismjs/fonts, zero refs; markdown stack fetches jsDelivr at runtime), `scripts/harvest-fixtures.mjs` (zero refs), and the 3 `node scripts/copy-vendor.js` lines in `.github/workflows/build-platforms.yml` (script deleted in the 15th run — CI was broken); kit `scripts/bundle-markdown.mjs` (orphaned, superseded by src/markdown.js).
|
|
12
|
+
|
|
13
|
+
**Witnessed** (localhost:3009/gm/?token, PASSWORD=`123,slam,123,slam`, fresh server + re-vendored dist, via gm `browser` verb): readyState complete, `ds-247420` dark body `rgb(19,19,24)`, 3 resizers, hScroll 0, rail `ds-search-input`=1 / bespoke `ds-session-search`=0 (consolidation landed), `ds-file-perm-tag`/`site-footer`/`ds-kbd-caps` rules all resolve, **0 console errors**. Kit build all 4 lints PASS. `test.js` 10 pass/0 fail. Re-vendored `dist/247420.{css,js}`.
|
|
14
|
+
|
|
3
15
|
## Design-maturity sweep + dead-code + server-hardening (2026-06-18) — fifteenth run
|
|
4
16
|
|
|
5
17
|
Mandate: "fix every aspect, update ../design, all design content lives there, fan out subagents, track with a workflow." Two tracking Workflows ran. **`gui-design-15` (run `wf_7ba315a1-9a9`, 8 lenses composer-input/chat-thread/files/sessions/shell/tokens-theme/a11y-motion/glyph-residue): 59 agents -> 42 findings -> 35 confirmed -> 33 applied across 9 kit files** + 2 deferred fixes implemented after (shell pane-toggle relocated into `.ws-crumb` as a `ws-desktop-toggle`; files density picker made icon-led with 3 NEW shell.js icons `rows`/`rows-tight`/`grid` + `DENSITY_ICONS` + `.ds-density-btn` 28px square). **`gui-design-15b` (run `wf_5b2861b2-717`, 3 lenses history-settings/server-boundary/security): 25 agents -> 22 findings -> 18 confirmed**, all landed. Total ~95 agents, ~4M tokens.
|
|
@@ -14,15 +26,11 @@ Mandate: "fix every aspect, update ../design, all design content lives there, fa
|
|
|
14
26
|
|
|
15
27
|
## Design-maturity sweep + marketing-site consolidation (2026-06-18) — fourteenth run
|
|
16
28
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
**Workflow `gui-design-14` (via the Workflow tool, run `wf_50751bd9-a43`, 7 lenses: chat-thread/files/sessions/shell-chrome/tokens-theme/a11y-motion/marketing-residue): 46 agents -> 39 findings -> 28 adversarially confirmed** (`PUNCHLIST-DESIGN-14.md`; 2 lens connection-failures: tokens-theme hunt + marketing-residue verify). ALL landed in the kit. **chat:** ThinkingNode base CSS (`.chat-thinking`/`-text`/`-dots` had ZERO base rules outside `.agentchat-working`), markdown `table`/`th`/`td`/`hr` (were unstyled -> bare cells), dead `.chat-tick` inline-code class given a rule, composer toolbar unified on 32px/`--r-1` (was 40px-round vs 36px-square), flat `.chat-md` rhythm+inset, streaming `.chat-stream-pre` persistent chrome, tool/code `:has()` measure-breakout. **files:** FileSkeleton container was a single 48px shimmer bar collapsing all rows (now inner `.ds-skel`-only), filter folded into one `.ds-file-controls` toolbar row, per-type cell icon tints, dead `data-columns` card-mode removed (+ `FILE_GRID_MIN_COL`/`columns` param), `.ds-file-check` dead font/color decls dropped + `.ds-check-box` rest border -> `--fg-3`. **sessions:** stale disc own tone (was sharing `--amber` with connecting) + connecting now a hollow ring, dead duplicate `.ds-dash-status.is-running` removed + running unified on `--accent` across disc/breakdown/card, `.seg.is-idle` weight 600, reduced-motion live-disc static-ring fallback, mixed-tick thickened 1.5px->2px, card cost as emphasized `.ds-dash-stat-cost`, conv-list unread -> hollow ring (shape-distinct from running). **shell:** resizers hidden past their staging breakpoints (`@media` 1480/1100/900 — were dead handles dragging vars into a fixed drawer), coarse-pointer 16px hit target, `WS_RESIZE_CLAMP` reconciled to the CSS `clamp()` floors/ceilings, localStorage committed on pointerup (not per-move), separator `aria-valuemin/max/now`. **a11y:** voice `vx-*` added to `community.css` reduced-motion guard, status discs given non-colour SHAPE channels, `.ds-input-bare` `:focus`->`:focus-visible`+ring. **Status-disc shape rule:** live=solid+pulse(or static ring under reduced-motion), error=solid+halo, connecting=hollow ring, stale=muted solid — four channels, not colour-only. Witnessed live (localhost:3009/gm/?token, PASSWORD=`123,slam,123,slam`): 0 console/page errors, dark body surface painted by kit, 3 resizers, no h-scroll, migrated classes resolve. Kit pushed `3704876`; rebased onto a concurrent CI `v0.0.211` bump.
|
|
29
|
+
`site/theme.mjs` (marketing renderer, NOT the SPA) was the last design residue -> migrated to a NEW kit `marketing.css` `.site-*` family; `Panel`/`Heading` gained a `class` prop; `Btn({primary})`->`Btn({variant:'primary'})`. Workflow `gui-design-14` (`wf_50751bd9-a43`, 7 lenses) 46 agents -> 28 confirmed, all in the kit (ThinkingNode/markdown-table/status-disc shape channels/shell resizer breakpoints). **Status-disc shape rule: live=solid+pulse, error=solid+halo, connecting=hollow ring, stale=muted solid.** Full detail in rs-learn (recall "agentgui 14th run marketing-site consolidation").
|
|
20
30
|
|
|
21
31
|
## Design-content consolidation — ALL design lives in the kit now (2026-06-18) — thirteenth run
|
|
22
32
|
|
|
23
|
-
The mandate: every design decision
|
|
24
|
-
|
|
25
|
-
**Workflow `.claude/workflows/gui-design-consolidation.js`** (residue-first 13th run, 6 lenses: design-residue/chat-thread/files-live/shell-chrome/tokens-theme/a11y-motion) ran 44 agents -> 19 confirmed findings (`PUNCHLIST-DESIGN.md`), ALL landed in the kit: composer send-row `.chat-composer-toolbar` (was unstyled), role-monotonic chat hover tints, tool-card `done` success tone, base-`Chat` `.chat-empty-suggestion` styling, error-card flame inset rail, `.ds-check-box` CSS-drawn multi-select checkbox (replaced the `[x]/[ ]` bracket text in files.js+sessions.js with a bordered box that fills on `.is-marked`/`[aria-checked]` — border-drawn tick, NOT a glyph), thin 26px status strip, status-item ellipsis, `.ws-crumb` gutter align, fluid `clamp()` shell width tokens, `:focus`->`:focus-visible` (no ring on mouse click), `--warn`/`--sky` dark-theme pairs, unified `--focus-*` tokens, reduced-motion skeleton static-fill, color-blind-safe rail SHAPE differentiation + sr-only status word in `Row()`. Amber/purple hardcoded `var(--token, #hex)` fallbacks stripped (the dark-hex could wrongly paint the light theme). **`lint-glyphs` was extended** with `SCAN_ROOT_FILES` (app-shell/chat/colors_and_type/community/community-app/editor-primitives/app-surfaces.css) — the root bundled CSS previously escaped the glyph lint, which is how 39 box-drawing comment dividers in app-shell.css slipped in (now converted to ASCII). Witnessed live (localhost:3009/gm/, fresh bundle): 0 console/page errors, migrated classes resolve from the kit bundle (`.pill` cursor:pointer/radius 999px, `.ds-check-box` 15px, cwd mono), no h-scroll.
|
|
33
|
+
The mandate's origin: every design decision lives in the kit (`../design`), none in agentgui. `site/app/index.html` lost its ~240-line inline `<style>` (moved to NEW kit `app-surfaces.css`); `app.js` carries zero inline `style=` props. **Rule going forward: no design content in agentgui — new surface styling is a kit CSS rule, never an inline `<style>` or `style=`.** `lint-glyphs` extended with `SCAN_ROOT_FILES` so root bundled CSS no longer escapes the glyph lint. Workflow `gui-design-consolidation.js` (6 lenses) 44 agents -> 19 confirmed. Full detail in rs-learn (recall "agentgui 13th run design-content consolidation").
|
|
26
34
|
|
|
27
35
|
## CRITICAL — `authedFetch` must NOT set `Authorization: Bearer` behind an nginx Basic-Auth proxy (2026-06-18)
|
|
28
36
|
|
package/lib/http-handler.js
CHANGED
|
@@ -37,6 +37,12 @@ export function confineToRoots(inputPath, allowRoots) {
|
|
|
37
37
|
return { ok: true, realPath };
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
// Secret-bearing basenames that must never be readable through ANY confined
|
|
41
|
+
// raw-bytes route (preview or download), even when they sit inside an allowed
|
|
42
|
+
// root: dotfiles, env/key/cert material, and credential stores. One const so
|
|
43
|
+
// /api/file and /api/download can never drift apart.
|
|
44
|
+
export const SECRET_RE = /(^\.|\.(env|pem|key|crt|p12|pfx)$|secret|credential|\.npmrc$|\.netrc$)/i;
|
|
45
|
+
|
|
40
46
|
// The allowlist the Files surface operates within: server cwd + Claude
|
|
41
47
|
// projects dir, widened via FS_ROOTS (path-separated). One construction so
|
|
42
48
|
// /api/list,file,download and the mutation routes can never drift apart.
|
|
@@ -403,7 +409,7 @@ export function createHttpHandler({ BASE_URL, expressApp, queries, sendJSON, ser
|
|
|
403
409
|
for (const [t, exts] of Object.entries(EXT_TYPE)) if (exts.includes(ext)) return t;
|
|
404
410
|
return 'other';
|
|
405
411
|
};
|
|
406
|
-
const dirents = fs.readdirSync(normalizedPath, { withFileTypes: true });
|
|
412
|
+
const dirents = fs.readdirSync(normalizedPath, { withFileTypes: true }).filter((d) => !SECRET_RE.test(d.name));
|
|
407
413
|
const entries = dirents.map((d) => {
|
|
408
414
|
const full = path.join(normalizedPath, d.name);
|
|
409
415
|
let size = null, modified = null, permissions;
|
|
@@ -449,7 +455,6 @@ export function createHttpHandler({ BASE_URL, expressApp, queries, sendJSON, ser
|
|
|
449
455
|
// material, and credential stores must never be readable through the
|
|
450
456
|
// Files preview even when they sit inside an allowed root.
|
|
451
457
|
const base = path.basename(normalizedPath);
|
|
452
|
-
const SECRET_RE = /(^\.|\.(env|pem|key|crt|p12|pfx)$|secret|credential|\.npmrc$|\.netrc$)/i;
|
|
453
458
|
if (SECRET_RE.test(base)) { res.writeHead(403); res.end('Forbidden'); return; }
|
|
454
459
|
// Only known text/code extensions (images go through /api/image). An
|
|
455
460
|
// unknown/binary extension is rejected, never served as octet-stream.
|
|
@@ -493,15 +498,19 @@ export function createHttpHandler({ BASE_URL, expressApp, queries, sendJSON, ser
|
|
|
493
498
|
const conf = confineToRoots(decodedPath, allowRoots);
|
|
494
499
|
if (!conf.ok) { res.writeHead(conf.reason === 'not found' ? 404 : 403); res.end('Forbidden'); return; }
|
|
495
500
|
const normalizedPath = conf.realPath;
|
|
501
|
+
// Same secret-name block as /api/file: a download must not exfiltrate
|
|
502
|
+
// .env/.pem/.key/credential material just because it streams bytes.
|
|
503
|
+
if (SECRET_RE.test(path.basename(normalizedPath))) { res.writeHead(403); res.end('Forbidden'); return; }
|
|
496
504
|
try {
|
|
497
505
|
const st = fs.statSync(normalizedPath);
|
|
498
506
|
if (!st.isFile()) { res.writeHead(400); res.end('Not a file'); return; }
|
|
499
507
|
const MAX = 50 * 1024 * 1024; // 50MB cap so a download can't exhaust memory
|
|
500
508
|
if (st.size > MAX) { res.writeHead(413); res.end('File too large to download'); return; }
|
|
501
|
-
const
|
|
509
|
+
const base = path.basename(normalizedPath);
|
|
510
|
+
const asciiName = base.replace(/[\\"\r\n]/g, '').replace(/[^\x20-\x7e]/g, '_');
|
|
502
511
|
res.writeHead(200, {
|
|
503
512
|
'Content-Type': 'application/octet-stream',
|
|
504
|
-
'Content-Disposition': 'attachment; filename="' +
|
|
513
|
+
'Content-Disposition': 'attachment; filename="' + asciiName + '"; filename*=UTF-8\'\'' + encodeURIComponent(base),
|
|
505
514
|
'Content-Length': String(st.size),
|
|
506
515
|
'Cache-Control': 'no-cache',
|
|
507
516
|
});
|
|
@@ -533,6 +542,7 @@ export function createHttpHandler({ BASE_URL, expressApp, queries, sendJSON, ser
|
|
|
533
542
|
if (isAllowRoot(conf.realPath, allowRoots)) { sendJSON(req, res, 403, { error: 'forbidden: cannot rename an allowed root' }); return; }
|
|
534
543
|
const newName = sanitizeEntryName(body.newName);
|
|
535
544
|
if (!newName) { sendJSON(req, res, 400, { error: 'invalid name' }); return; }
|
|
545
|
+
if (SECRET_RE.test(newName)) { sendJSON(req, res, 403, { error: 'forbidden: secret/dotfile name' }); return; }
|
|
536
546
|
const target = path.join(path.dirname(conf.realPath), newName);
|
|
537
547
|
// The target stays in the same (already-confined) directory by
|
|
538
548
|
// construction, but re-check anyway so the invariant is local.
|
|
@@ -622,6 +632,7 @@ export function createHttpHandler({ BASE_URL, expressApp, queries, sendJSON, ser
|
|
|
622
632
|
if (!conf.ok) { sendJSON(req, res, conf.reason === 'not found' ? 404 : 403, { error: 'forbidden: ' + conf.reason }); return; }
|
|
623
633
|
const name = sanitizeEntryName(body.name);
|
|
624
634
|
if (!name) { sendJSON(req, res, 400, { error: 'invalid name' }); return; }
|
|
635
|
+
if (SECRET_RE.test(name)) { sendJSON(req, res, 403, { error: 'forbidden: secret/dotfile name' }); return; }
|
|
625
636
|
const target = path.join(conf.realPath, name);
|
|
626
637
|
if (fs.existsSync(target)) { sendJSON(req, res, 409, { error: 'a file with that name already exists' }); return; }
|
|
627
638
|
try { fs.mkdirSync(target); sendJSON(req, res, 200, { ok: true, path: target }); }
|
|
@@ -641,6 +652,7 @@ export function createHttpHandler({ BASE_URL, expressApp, queries, sendJSON, ser
|
|
|
641
652
|
if (!conf.ok) { sendJSON(req, res, conf.reason === 'not found' ? 404 : 403, { error: 'forbidden: ' + conf.reason }); return; }
|
|
642
653
|
const name = sanitizeEntryName(qs.get('name'));
|
|
643
654
|
if (!name) { sendJSON(req, res, 400, { error: 'invalid name' }); return; }
|
|
655
|
+
if (SECRET_RE.test(name)) { sendJSON(req, res, 403, { error: 'forbidden: secret/dotfile name' }); return; }
|
|
644
656
|
const target = path.join(conf.realPath, name);
|
|
645
657
|
if (fs.existsSync(target) && qs.get('overwrite') !== '1') { sendJSON(req, res, 409, { error: 'a file with that name already exists' }); return; }
|
|
646
658
|
let buf;
|
package/package.json
CHANGED
|
@@ -1809,7 +1809,7 @@
|
|
|
1809
1809
|
transition: background var(--dur-snap) var(--ease), color var(--dur-snap) var(--ease);
|
|
1810
1810
|
}
|
|
1811
1811
|
.ds-247420 .ds-density-btn:hover { color: var(--fg); }
|
|
1812
|
-
.ds-247420 .ds-density-btn.active { background: var(--accent-tint); color: var(--
|
|
1812
|
+
.ds-247420 .ds-density-btn.active { background: var(--accent-tint); color: var(--fg); }
|
|
1813
1813
|
.ds-247420 .ds-density-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
|
|
1814
1814
|
|
|
1815
1815
|
/* Compact density — tighter rows for long listings. */
|
|
@@ -1834,6 +1834,10 @@
|
|
|
1834
1834
|
.ds-247420 .ds-file-cell.active { border-color: var(--accent); background: var(--accent-tint); }
|
|
1835
1835
|
.ds-247420 .ds-file-cell.is-marked { border-color: var(--accent); background: var(--accent-tint); }
|
|
1836
1836
|
.ds-247420 .ds-file-cell.is-locked { opacity: 0.6; }
|
|
1837
|
+
.ds-247420 .ds-file-row.is-locked { opacity: 0.6; }
|
|
1838
|
+
.ds-247420 .ds-file-row.is-restricted .title { color: var(--fg-2); }
|
|
1839
|
+
.ds-247420 .ds-file-perm-tag { font-family: var(--ff-mono); font-size: var(--fs-micro); color: var(--fg-3); padding: 1px 6px; border: var(--bw-hair) solid var(--rule); border-radius: var(--r-1); white-space: nowrap; }
|
|
1840
|
+
.ds-247420 .ds-file-perm-tag.is-noaccess { color: var(--flame); border-color: color-mix(in srgb, var(--flame) 40%, transparent); }
|
|
1837
1841
|
.ds-247420 .ds-file-cell-open {
|
|
1838
1842
|
display: flex; flex-direction: column; align-items: stretch; gap: var(--space-1);
|
|
1839
1843
|
width: 100%; padding: var(--space-1); margin: 0;
|
|
@@ -2230,6 +2234,10 @@
|
|
|
2230
2234
|
border-radius: var(--r-2); font-size: var(--fs-xs);
|
|
2231
2235
|
}
|
|
2232
2236
|
.ds-247420 .ds-shortcut-row { display: flex; align-items: center; gap: var(--space-2); }
|
|
2237
|
+
.ds-247420 .ds-shortcuts-hint .ds-kbd-label { flex: 1 1 auto; opacity: .85; }
|
|
2238
|
+
.ds-247420 .ds-shortcuts-hint .ds-kbd { white-space: normal; max-width: 100%; }
|
|
2239
|
+
.ds-247420 .ds-kbd-caps { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; }
|
|
2240
|
+
.ds-247420 .ds-kbd-sep { color: var(--fg-3); font-size: var(--fs-micro); padding: 0 2px; }
|
|
2233
2241
|
.ds-247420 .ds-kbd {
|
|
2234
2242
|
display: inline-block; min-width: 0;
|
|
2235
2243
|
padding: 2px 7px; border-radius: 6px;
|
|
@@ -2702,6 +2710,12 @@
|
|
|
2702
2710
|
.ds-247420 .chat-composer .send:disabled {
|
|
2703
2711
|
background: var(--bg-3); color: var(--fg-3); cursor: not-allowed; transform: none;
|
|
2704
2712
|
}
|
|
2713
|
+
@media (prefers-reduced-motion: reduce) {
|
|
2714
|
+
.ds-247420 .chat-composer,
|
|
2715
|
+
.ds-247420 .chat-composer textarea,
|
|
2716
|
+
.ds-247420 .chat-composer .send,
|
|
2717
|
+
.ds-247420 .composer-btn { transition: none; }
|
|
2718
|
+
}
|
|
2705
2719
|
|
|
2706
2720
|
.ds-247420 .aicat-portrait { display: inline-flex; align-items: center; gap: 10px; padding: 4px 0; }
|
|
2707
2721
|
.ds-247420 .aicat-face {
|
|
@@ -3694,6 +3708,7 @@
|
|
|
3694
3708
|
.ds-247420 .ws-pane-collapsed .ws-pane > * { display: none; }
|
|
3695
3709
|
@media (pointer: coarse) {
|
|
3696
3710
|
.ds-247420 .ws-rail-toggle { width: 44px; height: 44px; }
|
|
3711
|
+
.ds-247420 .ws-drawer-toggle { width: 44px; height: 44px; }
|
|
3697
3712
|
}
|
|
3698
3713
|
|
|
3699
3714
|
/* Drawer toggles and the scrim are hidden by default and revealed by the staged
|
|
@@ -3819,6 +3834,11 @@
|
|
|
3819
3834
|
.ds-247420 .ws-drawer-toggle:hover { background: var(--bg-2); color: var(--fg); }
|
|
3820
3835
|
.ds-247420 .ws-drawer-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
3821
3836
|
|
|
3837
|
+
@media (prefers-reduced-motion: reduce) {
|
|
3838
|
+
.ds-247420 .ws-shell, .ds-247420 .ws-rail, .ds-247420 .ws-pane, .ds-247420 .ws-sessions, .ds-247420 .ws-scrim { transition: none; }
|
|
3839
|
+
.ds-247420 .ws-resizer::after { transition: none; }
|
|
3840
|
+
}
|
|
3841
|
+
|
|
3822
3842
|
/* ============================================================
|
|
3823
3843
|
Row title highlight, expanded-row actions, filter pills.
|
|
3824
3844
|
============================================================ */
|
|
@@ -3849,7 +3869,7 @@
|
|
|
3849
3869
|
transition: background var(--dur-snap) var(--ease), color var(--dur-snap) var(--ease);
|
|
3850
3870
|
}
|
|
3851
3871
|
.ds-247420 .ds-filter-pill:hover { background: var(--bg-3); color: var(--fg); }
|
|
3852
|
-
.ds-247420 .ds-filter-pill.active { background: var(--accent-tint); color: var(--
|
|
3872
|
+
.ds-247420 .ds-filter-pill.active { background: var(--accent-tint); color: var(--fg); border-color: var(--accent); }
|
|
3853
3873
|
.ds-247420 .ds-filter-pill:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
|
|
3854
3874
|
|
|
3855
3875
|
/* Touch floor for the new small controls. */
|
|
@@ -4907,6 +4927,16 @@
|
|
|
4907
4927
|
border-radius: var(--r-1);
|
|
4908
4928
|
}
|
|
4909
4929
|
|
|
4930
|
+
/* ThreadPanel / Forum / Page interactive elements */
|
|
4931
|
+
.ds-247420 .cm-tp-item:focus-visible,
|
|
4932
|
+
.ds-247420 .cm-forum-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: var(--r-1); }
|
|
4933
|
+
.ds-247420 .cm-tp-new:focus-visible,
|
|
4934
|
+
.ds-247420 .cm-tp-close:focus-visible,
|
|
4935
|
+
.ds-247420 .cm-forum-new:focus-visible,
|
|
4936
|
+
.ds-247420 .cm-forum-sort:focus-visible,
|
|
4937
|
+
.ds-247420 .cm-page-edit:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--r-1); }
|
|
4938
|
+
.ds-247420 .cm-forum-search:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--accent); }
|
|
4939
|
+
|
|
4910
4940
|
/* ---------- mobile header ---------- */
|
|
4911
4941
|
.ds-247420 .cm-mobile-header {
|
|
4912
4942
|
display: flex;
|
|
@@ -5487,7 +5517,7 @@
|
|
|
5487
5517
|
background: none;
|
|
5488
5518
|
border: 1px solid var(--rule);
|
|
5489
5519
|
color: inherit;
|
|
5490
|
-
border-radius:
|
|
5520
|
+
border-radius: var(--r-1);
|
|
5491
5521
|
padding: 2px 8px;
|
|
5492
5522
|
cursor: pointer;
|
|
5493
5523
|
font: inherit;
|
|
@@ -5506,6 +5536,7 @@
|
|
|
5506
5536
|
}
|
|
5507
5537
|
.ds-247420 .agentchat-cwd-input:focus-visible { outline: none; box-shadow: var(--focus-ring-inset); }
|
|
5508
5538
|
.ds-247420 .agentchat-cwd-input[aria-invalid='true'] { border-color: var(--flame); box-shadow: inset 0 0 0 var(--bw-hair) var(--flame); }
|
|
5539
|
+
.ds-247420 .agentchat-cwd-input[aria-busy='true'] { border-color: var(--fg-3); box-shadow: inset 0 0 0 var(--bw-hair) var(--fg-3); }
|
|
5509
5540
|
|
|
5510
5541
|
/* head + thread */
|
|
5511
5542
|
.ds-247420 .agentchat-head {
|
|
@@ -5756,18 +5787,14 @@
|
|
|
5756
5787
|
}
|
|
5757
5788
|
.ds-247420 .ds-session-new > span { display: none; }
|
|
5758
5789
|
.ds-247420 .ds-session-new:hover { background: var(--bg-2); color: var(--fg); }
|
|
5759
|
-
|
|
5790
|
+
/* Rail filter uses the shared .ds-search-input primitive (provides bg/border/
|
|
5791
|
+
radius/focus-ring); only the rail layout + touch floor live here. */
|
|
5792
|
+
.ds-247420 .ds-session-head .ds-search-input { order: 1; flex: 1 1 auto; min-width: 0; }
|
|
5760
5793
|
.ds-247420 .ds-session-new:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
5761
|
-
.ds-247420 .ds-session-search {
|
|
5762
|
-
width: 100%; padding: var(--space-1) var(--space-3); min-height: 36px;
|
|
5763
|
-
background: var(--bg-2); border: var(--bw-hair) solid var(--bg-3); color: var(--fg);
|
|
5764
|
-
border-radius: var(--r-1); font-family: var(--ff-body); font-size: var(--fs-sm);
|
|
5765
|
-
}
|
|
5766
|
-
.ds-247420 .ds-session-search:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--accent); }
|
|
5767
5794
|
/* Touch floor (must FOLLOW the base rules - same specificity, order decides). */
|
|
5768
5795
|
@media (pointer: coarse) {
|
|
5769
5796
|
.ds-247420 .ds-session-new { width: 44px; min-height: 44px; }
|
|
5770
|
-
.ds-247420 .ds-session-search { min-height: 44px; }
|
|
5797
|
+
.ds-247420 .ds-session-head .ds-search-input { min-height: 44px; }
|
|
5771
5798
|
}
|
|
5772
5799
|
.ds-247420 .ds-session-list, .ds-247420 .ds-session-groups { flex: 1; min-height: 0; overflow-y: auto; padding: var(--space-2); }
|
|
5773
5800
|
/* Grouped rows (Today/Yesterday/...) lay out like the flat list; the section
|
|
@@ -5946,7 +5973,7 @@
|
|
|
5946
5973
|
border-radius: var(--r-1); background: var(--bg-2); color: var(--fg-2);
|
|
5947
5974
|
cursor: pointer; font-family: var(--ff-body); font-size: var(--fs-tiny);
|
|
5948
5975
|
}
|
|
5949
|
-
.ds-247420 .ds-dash-errors-toggle.active { background: var(--accent-tint); color: var(--
|
|
5976
|
+
.ds-247420 .ds-dash-errors-toggle.active { background: var(--accent-tint); color: var(--fg); border-color: var(--accent); }
|
|
5950
5977
|
.ds-247420 .ds-dash-errors-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
|
|
5951
5978
|
|
|
5952
5979
|
/* --- C3: per-card select checkbox. --- */
|
|
@@ -6114,6 +6141,7 @@
|
|
|
6114
6141
|
/* Inline cwd validation line (checking / error) under the cwd input. */
|
|
6115
6142
|
.ds-247420 .agentchat-cwd-hint { font-size: var(--fs-tiny); color: var(--fg-3); }
|
|
6116
6143
|
.ds-247420 .agentchat-cwd-hint.is-error { color: var(--flame); }
|
|
6144
|
+
.ds-247420 .agentchat-cwd-hint.is-checking { color: var(--fg-2); font-style: italic; }
|
|
6117
6145
|
|
|
6118
6146
|
/* Dashboard: shared session title heading (same string as the rails). */
|
|
6119
6147
|
.ds-247420 .ds-dash-title {
|
|
@@ -6213,6 +6241,7 @@
|
|
|
6213
6241
|
}
|
|
6214
6242
|
.ds-247420 .chat-msg .chat-tool .chat-tool-head::-webkit-details-marker { display: none; }
|
|
6215
6243
|
.ds-247420 .chat-msg .chat-tool .chat-tool-head:hover { background: var(--bg-2); }
|
|
6244
|
+
.ds-247420 .chat-msg .chat-tool .chat-tool-head:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
|
|
6216
6245
|
.ds-247420 .chat-tool-icon { display: inline-flex; color: var(--fg-3); }
|
|
6217
6246
|
.ds-247420 .chat-tool-name { font-family: var(--ff-mono); font-weight: 600; color: var(--fg); }
|
|
6218
6247
|
.ds-247420 .chat-tool-label { color: var(--fg-3); font-size: var(--fs-tiny); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
|
|
@@ -6233,6 +6262,7 @@
|
|
|
6233
6262
|
.ds-247420 .chat-tool-section-label { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); font-size: var(--fs-tiny); font-weight: 600; text-transform: uppercase; letter-spacing: var(--tr-caps); color: var(--fg-3); }
|
|
6234
6263
|
.ds-247420 .chat-tool-copy { position: static; opacity: 0; }
|
|
6235
6264
|
.ds-247420 .chat-tool-section:hover .chat-tool-copy, .ds-247420 .chat-tool-section:focus-within .chat-tool-copy { opacity: 1; }
|
|
6265
|
+
.ds-247420 .chat-tool-copy:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; opacity: 1; }
|
|
6236
6266
|
.ds-247420 .chat-tool-pre { margin: 0; padding: var(--space-2); background: var(--bg-2); border-radius: var(--r-1); font-family: var(--ff-mono); font-size: var(--fs-tiny); line-height: 1.45; overflow-x: auto; max-height: 320px; overflow-y: auto; }
|
|
6237
6267
|
.ds-247420 .chat-tool-pre.is-error { color: var(--flame); }
|
|
6238
6268
|
.ds-247420 .chat-tool-pre.chat-tool-empty { color: var(--fg-3); }
|
|
@@ -6288,15 +6318,17 @@
|
|
|
6288
6318
|
.ds-247420 .ds-dash-breakdown .seg { display: inline-flex; align-items: center; gap: var(--space-1); font-weight: 600; }
|
|
6289
6319
|
.ds-247420 .ds-dash-breakdown .seg::before { content: ''; width: 7px; height: 7px; border-radius: 50%; flex: none; }
|
|
6290
6320
|
.ds-247420 .ds-dash-breakdown .seg.is-running { color: var(--accent); }
|
|
6291
|
-
.ds-247420 .ds-dash-breakdown .seg.is-running::before { background: var(--accent); }
|
|
6321
|
+
.ds-247420 .ds-dash-breakdown .seg.is-running::before { background: var(--accent); box-shadow: 0 0 0 1.5px color-mix(in oklab, var(--accent) 30%, transparent); }
|
|
6292
6322
|
.ds-247420 .ds-dash-breakdown .seg.is-error { color: var(--flame); }
|
|
6293
6323
|
.ds-247420 .ds-dash-breakdown .seg.is-error::before { background: var(--flame); box-shadow: 0 0 0 1.5px color-mix(in oklab, var(--flame) 38%, transparent); }
|
|
6294
|
-
.ds-247420 .ds-dash-breakdown .seg.is-idle { color: var(--
|
|
6295
|
-
.ds-247420 .ds-dash-breakdown .seg.is-idle::before { background: transparent; box-shadow: inset 0 0 0
|
|
6324
|
+
.ds-247420 .ds-dash-breakdown .seg.is-idle { color: var(--stale); }
|
|
6325
|
+
.ds-247420 .ds-dash-breakdown .seg.is-idle::before { background: transparent; box-shadow: inset 0 0 0 1px var(--stale), inset 0 0 0 3px var(--bg); }
|
|
6296
6326
|
.ds-247420 .ds-dash-stream-disc { display: inline-flex; align-items: center; gap: var(--space-1); }
|
|
6297
6327
|
.ds-247420 .ds-dash-selectall { display: inline-flex; align-items: center; gap: var(--space-1); font-size: var(--fs-tiny); color: var(--fg-2); cursor: pointer; background: none; border: none; padding: var(--space-1); }
|
|
6298
6328
|
.ds-247420 .ds-dash-selectall:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
|
|
6299
6329
|
.ds-247420 .ds-dash-clear { background: none; border: none; color: var(--fg-3); cursor: pointer; font-size: var(--fs-tiny); text-decoration: underline dotted; padding: var(--space-1); }
|
|
6330
|
+
.ds-247420 .ds-dash-clear:hover { color: var(--fg); }
|
|
6331
|
+
.ds-247420 .ds-dash-clear:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; border-radius: var(--r-1); }
|
|
6300
6332
|
|
|
6301
6333
|
/* Conversation-rail loading skeleton (cold ccsniff walk). */
|
|
6302
6334
|
.ds-247420 .ds-session-row-skeleton { display: flex; flex-direction: column; gap: 6px; padding: var(--space-2) var(--space-3); }
|
|
@@ -7504,7 +7536,7 @@
|
|
|
7504
7536
|
.ds-247420 .ds-input-check:checked { background: var(--accent); border-color: var(--accent); }
|
|
7505
7537
|
.ds-247420 .ds-input-check:checked::after {
|
|
7506
7538
|
content: ''; position: absolute; left: 4px; top: 1px;
|
|
7507
|
-
width: 4px; height: 8px; border: solid var(--accent-fg
|
|
7539
|
+
width: 4px; height: 8px; border: solid var(--accent-fg);
|
|
7508
7540
|
border-width: 0 2px 2px 0; transform: rotate(45deg);
|
|
7509
7541
|
}
|
|
7510
7542
|
.ds-247420 .ds-input-check:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
@@ -7546,7 +7578,7 @@
|
|
|
7546
7578
|
-webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
|
|
7547
7579
|
border: 1px solid var(--rule);
|
|
7548
7580
|
border-radius: var(--r-2, 8px);
|
|
7549
|
-
box-shadow:
|
|
7581
|
+
box-shadow: var(--shadow-3);
|
|
7550
7582
|
color: var(--panel-text);
|
|
7551
7583
|
overflow: hidden;
|
|
7552
7584
|
}
|
|
@@ -7913,6 +7945,10 @@
|
|
|
7913
7945
|
}
|
|
7914
7946
|
|
|
7915
7947
|
@media print {
|
|
7948
|
+
/* Re-assert the paper-tuned signal tokens so token-derived foregrounds
|
|
7949
|
+
(status discs, error text, tool cards) print with light-theme colours
|
|
7950
|
+
rather than the dark-theme-derived values inherited under auto-dark. */
|
|
7951
|
+
.ds-247420 { --flame:#C53E00; --amber:#8A6512; --warn:#E0241A; --sky:#3A6EFF; --bg:var(--paper); --fg:var(--ink); }
|
|
7916
7952
|
.ds-247420 #app { min-height: auto; display: block; height: auto; }
|
|
7917
7953
|
.ds-247420 .skip-link, .ds-247420 .status-dot, .ds-247420 .history-actions, .ds-247420 .chat-composer { display: none !important; }
|
|
7918
7954
|
.ds-247420 .app, .ds-247420 .app-main, .ds-247420 .panel, .ds-247420 .chat, .ds-247420 .chat-thread {
|
|
@@ -7930,20 +7966,28 @@
|
|
|
7930
7966
|
.ds-247420 .site-panel { margin: var(--space-2); }
|
|
7931
7967
|
|
|
7932
7968
|
/* Hero block */
|
|
7933
|
-
.ds-247420 .site-hero { padding:
|
|
7969
|
+
.ds-247420 .site-hero { padding: var(--space-4); }
|
|
7934
7970
|
.ds-247420 .site-hero-h { margin: 0 0 var(--space-2); }
|
|
7935
7971
|
.ds-247420 .site-hero-body { margin: var(--space-2) 0 var(--space-3); color: var(--fg-2); max-width: 64ch; }
|
|
7936
7972
|
.ds-247420 .site-chip-row { display: flex; gap: 6px; flex-wrap: wrap; margin: 0 0 var(--space-3); }
|
|
7937
7973
|
.ds-247420 .site-cta-row { display: flex; gap: var(--space-2); flex-wrap: wrap; }
|
|
7938
7974
|
|
|
7939
7975
|
/* Quickstart CLI block — these .cli/.prompt/.cmd nodes were previously unstyled. */
|
|
7940
|
-
.ds-247420 .site-cli { padding:
|
|
7941
|
-
.ds-247420 .site-cli .cli { display: flex; gap: var(--space-2); font-family: var(--ff-mono); font-size: var(--fs-sm); padding: 2px 0; }
|
|
7976
|
+
.ds-247420 .site-cli { padding: var(--space-3); background: var(--bg); border: var(--bw-hair, 1px) solid var(--rule); border-radius: var(--r-1); }
|
|
7977
|
+
.ds-247420 .site-cli .cli { display: flex; align-items: baseline; gap: var(--space-2); font-family: var(--ff-mono); font-size: var(--fs-sm); padding: 2px 0; }
|
|
7942
7978
|
.ds-247420 .site-cli .prompt { color: var(--fg-3); user-select: none; flex: 0 0 auto; }
|
|
7943
7979
|
.ds-247420 .site-cli .cmd { color: var(--fg); white-space: pre-wrap; word-break: break-word; }
|
|
7944
7980
|
|
|
7945
|
-
/* Embedded legacy doc (iframe wrapper)
|
|
7946
|
-
|
|
7981
|
+
/* Embedded legacy doc (iframe wrapper). 180px = the page chrome (topbar +
|
|
7982
|
+
* crumb + footer) sitting above the embed; dvh keeps it mobile-safe. */
|
|
7983
|
+
.ds-247420 .site-embed { width: 100%; height: calc(100dvh - 180px); min-height: 320px; border: 0; border-radius: var(--r-1); background: var(--bg-2); display: block; }
|
|
7984
|
+
|
|
7985
|
+
/* Marketing footer family (the in-app .app-status strip suppresses content
|
|
7986
|
+
* below 1100px; the site footer always shows its credits row). */
|
|
7987
|
+
.ds-247420 .site-footer { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); width: 100%; padding: var(--space-3) var(--space-4); font-family: var(--ff-body); font-size: var(--fs-sm); line-height: 1.4; color: var(--fg-3); border-top: 1px solid var(--rule); }
|
|
7988
|
+
.ds-247420 .site-footer .item { color: inherit; }
|
|
7989
|
+
.ds-247420 .site-footer .item:first-of-type { color: var(--accent); }
|
|
7990
|
+
.ds-247420 .site-footer .spread { flex: 1; }
|
|
7947
7991
|
|
|
7948
7992
|
/* spoint/loading-screen.css */
|
|
7949
7993
|
/* Loading-screen kit styles. Scoped under .ds-247420 at build time.
|