agentgui 1.0.943 → 1.0.944

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/CHANGELOG.md CHANGED
@@ -1,4 +1,9 @@
1
- ## [Unreleased] - Antigravity (agy) orchestration + glyph-to-ASCII sweep + spawn-injection fix
1
+ ## [Unreleased] - live e2e chat verified + composer caret fix + ccsniff memory cap
2
+
3
+ - verified the full GUI chat round-trip end-to-end in a real browser: compose -> WS chat.sendMessage -> claude-code -> streaming_progress -> transcript renders the streamed reply (not just the runner harness).
4
+ - site/app/js/app.js: composer onInput re-renders only on the empty<->non-empty draft transition (the only change that toggles the send button), not on every keystroke. Why: a synchronous re-render per character fought the caret on the controlled textarea.
5
+ - vendored anentrypoint-design DS rebuilt: ChatComposer reads the live textarea value on send and syncs the controlled value into the DOM only when it differs, so a mid-type re-render no longer resets the caret or drops keystrokes. Why: DS override belongs in the kit; the composer is shared.
6
+ - ccsniff (sibling repo, pushed): bounded the in-memory history store (event cap + eviction + per-event text cap) and bounded loadOnce to read newest events first up to the cap. Why: the store grew unbounded to 6GB+ (OOM) and parsed the entire JSONL backlog at load (~2.4GB transient peak); heap now settles ~47MB and load peak ~570MB.
2
7
 
3
8
  - lib/agent-discovery.js + lib/claude-runner-agents.js + lib/agent-descriptors.js: added `agy` (Antigravity) as a direct-protocol CLI agent — `agy --print "<prompt>" --dangerously-skip-permissions [--continue]`, plain-text parseOutput, no model picker. Completes the four flagship orchestration targets (Claude Code, OpenCode, Kilo, Antigravity). Why: the GUI could not drive Antigravity at all.
4
9
  - lib/claude-runner.js + lib/claude-runner-direct.js: SECURITY — the direct runner now spawns a resolved binary with `shell:false`. Previously `shell:true` on Windows concatenated argv unescaped, so a prompt containing `&`/`|`/`>`/backticks executed as shell commands (verified injection). Why: arbitrary command execution from chat input.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentgui",
3
- "version": "1.0.943",
3
+ "version": "1.0.944",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "electron/main.js",
@@ -434,7 +434,16 @@ function chatMain() {
434
434
  value: state.chat.draft,
435
435
  disabled: !canSend(),
436
436
  placeholder,
437
- onInput: (v) => { state.chat.draft = v; render(); },
437
+ // The DS textarea is controlled and reads its live DOM value on send, so we
438
+ // do NOT re-render on every keystroke (that fights the cursor and is wasteful).
439
+ // Re-render only when the draft crosses empty<->non-empty, since that is the
440
+ // only transition that changes the send button's disabled state.
441
+ onInput: (v) => {
442
+ const was = !!(state.chat.draft && state.chat.draft.trim());
443
+ const now = !!(v && v.trim());
444
+ state.chat.draft = v;
445
+ if (was !== now) render();
446
+ },
438
447
  onSend: (v) => { state.chat.draft = v; sendChat(); },
439
448
  });
440
449
 
@@ -518,14 +518,43 @@
518
518
 
519
519
  .ds-247420 .app-topbar {
520
520
  position: sticky; top: 0; z-index: var(--z-header);
521
- display: grid; grid-template-columns: auto 1fr auto;
521
+ display: flex; flex-wrap: wrap;
522
522
  align-items: center; gap: var(--space-4);
523
523
  min-height: var(--app-topbar-h);
524
524
  padding: 10px var(--pad-x);
525
525
  background: color-mix(in oklab, var(--bg) 88%, transparent);
526
526
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
527
527
  }
528
- .ds-247420 .app-topbar nav { display: flex; gap: 4px; font-size: var(--fs-sm); }
528
+
529
+ /* Merged chrome: when AppShell gets both a topbar and a crumb it wraps them
530
+ in .app-chrome and they share ONE sticky band instead of stacking as two
531
+ bars. The breadcrumb provides the left identity (it already begins with the
532
+ brand), so the topbar's standalone brand is hidden to avoid showing the name
533
+ twice; nav and the crumb's right slot sit together on the right. */
534
+ .ds-247420 .app-chrome {
535
+ position: sticky; top: 0; z-index: var(--z-header);
536
+ display: flex; flex-wrap: wrap; align-items: center;
537
+ gap: var(--space-2) var(--space-4);
538
+ padding: 8px var(--pad-x);
539
+ background: color-mix(in oklab, var(--bg) 88%, transparent);
540
+ backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
541
+ }
542
+ .ds-247420 .app-chrome > .app-topbar,
543
+ .ds-247420 .app-chrome > .app-crumb {
544
+ position: static; background: none; backdrop-filter: none;
545
+ -webkit-backdrop-filter: none; padding: 0; min-height: 0;
546
+ flex: 1 1 auto;
547
+ }
548
+ .ds-247420 .app-chrome > .app-crumb { order: 1; flex: 1 1 auto; }
549
+ .ds-247420 .app-chrome > .app-topbar { order: 2; flex: 0 0 auto; }
550
+ .ds-247420 .app-chrome > .app-topbar > .brand { display: none; }
551
+ .ds-247420 .app-chrome > .app-topbar > nav { margin-left: 0; }
552
+ .ds-247420 .app-chrome > .app-crumb > .crumb-right { margin-left: auto; }
553
+ .ds-247420 .app-topbar > .brand { flex: 0 0 auto; }
554
+ .ds-247420 .app-topbar > .app-search { flex: 1 1 auto; }
555
+ .ds-247420 .app-topbar > nav { margin-left: auto; }
556
+ .ds-247420 .app-topbar nav { display: flex; gap: 4px; font-size: var(--fs-sm); flex-wrap: wrap; }
557
+ .ds-247420 .app-topbar nav a { flex: 0 0 auto; }
529
558
  .ds-247420 .app-topbar nav a {
530
559
  color: var(--fg-2);
531
560
  padding: 12px 14px;
@@ -1083,25 +1112,21 @@
1083
1112
  /* App Layout: single-column + drawer is handled once in the ≤900px block;
1084
1113
  no need to re-declare grid-template-columns here (was a redundant !important). */
1085
1114
 
1086
- /* Topbar Navigation */
1115
+ /* Topbar Navigation: stack the nav onto its own full-width row below the
1116
+ brand and let it scroll horizontally. The brand stays on the first row;
1117
+ nav wraps to a second row at 100% width (flex-wrap on .app-topbar). */
1087
1118
  .ds-247420 .app-topbar {
1088
- grid-template-columns: 1fr auto;
1089
1119
  gap: var(--space-2); padding: 12px var(--space-3);
1090
1120
  }
1091
- .ds-247420 .app-topbar nav a {
1092
- padding: 12px 10px;
1093
- min-height: 44px;
1094
- }
1095
- /* Keep primary nav reachable on small screens (apps without a sidebar have
1096
- no other entry point). Compact it and let it scroll horizontally rather
1097
- than hiding it entirely. */
1098
- .ds-247420 .app-topbar nav {
1099
- display: flex; gap: 2px;
1121
+ .ds-247420 .app-topbar > nav {
1122
+ flex: 1 1 100%; margin-left: 0; order: 3;
1123
+ display: flex; gap: 2px; flex-wrap: nowrap;
1100
1124
  overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
1101
- max-width: 60vw;
1102
1125
  }
1103
1126
  .ds-247420 .app-topbar nav::-webkit-scrollbar { display: none; }
1104
- .ds-247420 .app-topbar nav a { padding: 10px 8px; white-space: nowrap; }
1127
+ .ds-247420 .app-topbar nav a {
1128
+ flex: 0 0 auto; padding: 10px 12px; min-height: 44px; white-space: nowrap;
1129
+ }
1105
1130
  .ds-247420 .brand { font-size: var(--fs-tiny); font-weight: 600; }
1106
1131
 
1107
1132
  /* Search */